From 4e38d36d88ead4e56f3155573976da84d5df18b3 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 28 Jul 2005 13:16:30 -0700 Subject: [PATCH] [IB/cm]: Correct CM port redirect reject codes Reject code 24 is port and CM redirection, not just port redirection. Port redirection alone is code 25. Therefore we should rename code 24 to IB_CM_REJ_PORT_CM_REDIRECT and use IB_CM_REJ_PORT_REDIRECT for code 25. Signed-off-by: Roland Dreier --- drivers/infiniband/include/ib_cm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/include/ib_cm.h b/drivers/infiniband/include/ib_cm.h index e5d74a730a70..da650115e79a 100644 --- a/drivers/infiniband/include/ib_cm.h +++ b/drivers/infiniband/include/ib_cm.h @@ -169,7 +169,8 @@ enum ib_cm_rej_reason { IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = __constant_htons(21), IB_CM_REJ_INVALID_ALT_HOP_LIMIT = __constant_htons(22), IB_CM_REJ_INVALID_ALT_PACKET_RATE = __constant_htons(23), - IB_CM_REJ_PORT_REDIRECT = __constant_htons(24), + IB_CM_REJ_PORT_CM_REDIRECT = __constant_htons(24), + IB_CM_REJ_PORT_REDIRECT = __constant_htons(25), IB_CM_REJ_INVALID_MTU = __constant_htons(26), IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = __constant_htons(27), IB_CM_REJ_CONSUMER_DEFINED = __constant_htons(28), -- cgit v1.2.3 From 0dca0f7bf82face7b700890318d5550fd542cabf Mon Sep 17 00:00:00 2001 From: Hal Rosenstock Date: Thu, 28 Jul 2005 13:17:26 -0700 Subject: [PATCH] [IPoIB] Handle sending of unicast RARP responses RARP replies are another valid case where IPoIB may need to send a unicast packet with no neighbour structure. Signed-off-by: Hal Rosenstock Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 6f60abbaebd5..fa00816a3cf7 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -600,9 +600,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb); } else { - /* unicast GID -- should be ARP reply */ + /* unicast GID -- should be ARP or RARP reply */ - if (be16_to_cpup((u16 *) skb->data) != ETH_P_ARP) { + if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) && + (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) { ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x " IPOIB_GID_FMT "\n", skb->dst ? "neigh" : "dst", -- cgit v1.2.3 From 4a7164023959040e687e51663dee67cff4d2b770 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Fri, 29 Jul 2005 15:51:36 -0400 Subject: [ACPI] Fix the regression with c1_default_handler on some systems where C-states come from FADT. Thanks to Kevin Radloff for identifying the issue and isolating it to exact line of code that is causing the issue. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 8f038cd29477..aea745f4a8b0 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -842,7 +842,7 @@ static int acpi_processor_get_power_info ( result = acpi_processor_get_power_info_cst(pr); if ((result) || (acpi_processor_power_verify(pr) < 2)) { result = acpi_processor_get_power_info_fadt(pr); - if (result) + if ((result) || (acpi_processor_power_verify(pr) < 2)) result = acpi_processor_get_power_info_default_c1(pr); } -- cgit v1.2.3 From 0b6b2f08c24a65535cb18893ca27516389c5fc0f Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Fri, 29 Jul 2005 16:00:13 -0400 Subject: [ACPI] Fix memset arguments in acpi processor_idle.c http://bugzilla.kernel.org/show_bug.cgi?id=4954 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index aea745f4a8b0..42b34f5df98b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -549,7 +549,8 @@ static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr) ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) - memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); + memset(&(pr->power.states[i]), 0, + sizeof(struct acpi_processor_cx)); /* if info is obtained from pblk/fadt, type equals state */ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; @@ -580,7 +581,8 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr) pr->power.count = 0; for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) - memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); + memset(&(pr->power.states[i]), 0, + sizeof(struct acpi_processor_cx)); status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); if (ACPI_FAILURE(status)) { -- cgit v1.2.3 From 335f16be5d917334f56ec9ef7ecf983476ac0563 Mon Sep 17 00:00:00 2001 From: David Shaohua Li Date: Wed, 22 Jun 2005 18:37:00 -0400 Subject: [ACPI] address boot-freeze with updated DMI blacklist for c-states http://bugzilla.kernel.org/show_bug.cgi?id=4763 Signed-off-by: David Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 42b34f5df98b..3702725db97a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -81,30 +81,33 @@ module_param(bm_history, uint, 0644); * * To skip this limit, boot/load with a large max_cstate limit. */ -static int no_c2c3(struct dmi_system_id *id) +static int set_max_cstate(struct dmi_system_id *id) { if (max_cstate > ACPI_PROCESSOR_MAX_POWER) return 0; - printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled." + printk(KERN_NOTICE PREFIX "%s detected - %s disabled." " Override with \"processor.max_cstate=%d\"\n", id->ident, + ((int)id->driver_data == 1)? "C2,C3":"C3", ACPI_PROCESSOR_MAX_POWER + 1); - max_cstate = 1; + max_cstate = (int)id->driver_data; return 0; } - - static struct dmi_system_id __initdata processor_power_dmi_table[] = { - { no_c2c3, "IBM ThinkPad R40e", { + { set_max_cstate, "IBM ThinkPad R40e", { DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }}, - { no_c2c3, "Medion 41700", { + DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1}, + { set_max_cstate, "Medion 41700", { + DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), + DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }, (void*)1}, + { set_max_cstate, "Clevo 5600D", { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), - DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }}, + DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307") }, + (void*)2}, {}, }; -- cgit v1.2.3 From 45bea1555f5bf0cd5871b208b4b02d188f106861 Mon Sep 17 00:00:00 2001 From: Luming Yu Date: Sat, 23 Jul 2005 04:08:00 -0400 Subject: [ACPI] Add "ec_polling" boot option EC burst mode benefits many machines, some of them significantly. However, our current implementation fails on some machines such as Rafael's Asus L5D. This patch restores the alternative EC polling code, which can be enabled at boot time via "ec_polling" http://bugzilla.kernel.org/show_bug.cgi?id=4665 Signed-off-by: Luming Yu Signed-off-by: Len Brown --- drivers/acpi/ec.c | 893 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 722 insertions(+), 171 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fca4140a50a9..2dadb7f63269 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -59,76 +59,185 @@ ACPI_MODULE_NAME ("acpi_ec") #define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ +#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ +#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ + #define ACPI_EC_COMMAND_READ 0x80 #define ACPI_EC_COMMAND_WRITE 0x81 #define ACPI_EC_BURST_ENABLE 0x82 #define ACPI_EC_BURST_DISABLE 0x83 #define ACPI_EC_COMMAND_QUERY 0x84 -static int acpi_ec_add (struct acpi_device *device); +#define EC_POLLING 0xFF +#define EC_BURST 0x00 + + static int acpi_ec_remove (struct acpi_device *device, int type); static int acpi_ec_start (struct acpi_device *device); static int acpi_ec_stop (struct acpi_device *device, int type); +static int acpi_ec_burst_add ( struct acpi_device *device); static struct acpi_driver acpi_ec_driver = { .name = ACPI_EC_DRIVER_NAME, .class = ACPI_EC_CLASS, .ids = ACPI_EC_HID, .ops = { - .add = acpi_ec_add, + .add = acpi_ec_burst_add, .remove = acpi_ec_remove, .start = acpi_ec_start, .stop = acpi_ec_stop, }, }; - -struct acpi_ec { - acpi_handle handle; - unsigned long uid; - unsigned long gpe_bit; - struct acpi_generic_address status_addr; - struct acpi_generic_address command_addr; - struct acpi_generic_address data_addr; - unsigned long global_lock; - unsigned int expect_event; - atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ - atomic_t pending_gpe; - struct semaphore sem; - wait_queue_head_t wait; +union acpi_ec { + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + } common; + + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + unsigned int expect_event; + atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort*/ + atomic_t pending_gpe; + struct semaphore sem; + wait_queue_head_t wait; + }burst; + + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + spinlock_t lock; + }polling; }; +static int acpi_ec_polling_wait ( union acpi_ec *ec, u8 event); +static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event); +static int acpi_ec_polling_read ( union acpi_ec *ec, u8 address, u32 *data); +static int acpi_ec_burst_read( union acpi_ec *ec, u8 address, u32 *data); +static int acpi_ec_polling_write ( union acpi_ec *ec, u8 address, u8 data); +static int acpi_ec_burst_write ( union acpi_ec *ec, u8 address, u8 data); +static int acpi_ec_polling_query ( union acpi_ec *ec, u32 *data); +static int acpi_ec_burst_query ( union acpi_ec *ec, u32 *data); +static void acpi_ec_gpe_polling_query ( void *ec_cxt); +static void acpi_ec_gpe_burst_query ( void *ec_cxt); +static u32 acpi_ec_gpe_polling_handler ( void *data); +static u32 acpi_ec_gpe_burst_handler ( void *data); +static acpi_status __init +acpi_fake_ecdt_polling_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval); + +static acpi_status __init +acpi_fake_ecdt_burst_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval); + +static int __init +acpi_ec_polling_get_real_ecdt(void); +static int __init +acpi_ec_burst_get_real_ecdt(void); /* If we find an EC via the ECDT, we need to keep a ptr to its context */ -static struct acpi_ec *ec_ecdt; +static union acpi_ec *ec_ecdt; /* External interfaces use first EC only, so remember */ static struct acpi_device *first_ec; +static int acpi_ec_polling_mode; /* -------------------------------------------------------------------------- Transaction Management -------------------------------------------------------------------------- */ -static inline u32 acpi_ec_read_status(struct acpi_ec *ec) +static inline u32 acpi_ec_read_status(union acpi_ec *ec) { u32 status = 0; - acpi_hw_low_level_read(8, &status, &ec->status_addr); + acpi_hw_low_level_read(8, &status, &ec->common.status_addr); return status; } -static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event) +static int +acpi_ec_wait ( + union acpi_ec *ec, + u8 event) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_wait (ec, event); + else + return acpi_ec_burst_wait (ec, event); +} + +static int +acpi_ec_polling_wait ( + union acpi_ec *ec, + u8 event) +{ + u32 acpi_ec_status = 0; + u32 i = ACPI_EC_UDELAY_COUNT; + + if (!ec) + return -EINVAL; + + /* Poll the EC status register waiting for the event to occur. */ + switch (event) { + case ACPI_EC_EVENT_OBF: + do { + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); + if (acpi_ec_status & ACPI_EC_FLAG_OBF) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + case ACPI_EC_EVENT_IBE: + do { + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->common.status_addr); + if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i>0); + break; + default: + return -EINVAL; + } + + return -ETIME; +} +static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) { int result = 0; ACPI_FUNCTION_TRACE("acpi_ec_wait"); - ec->expect_event = event; + ec->burst.expect_event = event; smp_mb(); - result = wait_event_interruptible_timeout(ec->wait, - !ec->expect_event, + result = wait_event_interruptible_timeout(ec->burst.wait, + !ec->burst.expect_event, msecs_to_jiffies(ACPI_EC_DELAY)); - ec->expect_event = 0; + ec->burst.expect_event = 0; smp_mb(); if (result < 0){ @@ -160,7 +269,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, unsigned int event) static int acpi_ec_enter_burst_mode ( - struct acpi_ec *ec) + union acpi_ec *ec) { u32 tmp = 0; int status = 0; @@ -170,43 +279,43 @@ acpi_ec_enter_burst_mode ( status = acpi_ec_read_status(ec); if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)){ - acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); return_VALUE(-EINVAL); } - acpi_hw_low_level_read(8, &tmp, &ec->data_addr); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if(tmp != 0x90 ) {/* Burst ACK byte*/ return_VALUE(-EINVAL); } } - atomic_set(&ec->leaving_burst , 0); + atomic_set(&ec->burst.leaving_burst , 0); return_VALUE(0); } static int acpi_ec_leave_burst_mode ( - struct acpi_ec *ec) + union acpi_ec *ec) { int status =0; ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); - atomic_set(&ec->leaving_burst , 1); + atomic_set(&ec->burst.leaving_burst , 1); status = acpi_ec_read_status(ec); if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){ - acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n")); return_VALUE(-EINVAL); } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); status = acpi_ec_read_status(ec); } @@ -215,7 +324,131 @@ acpi_ec_leave_burst_mode ( static int acpi_ec_read ( - struct acpi_ec *ec, + union acpi_ec *ec, + u8 address, + u32 *data) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_read(ec, address, data); + else + return acpi_ec_burst_read(ec, address, data); +} +static int +acpi_ec_write ( + union acpi_ec *ec, + u8 address, + u8 data) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_write(ec, address, data); + else + return acpi_ec_burst_write(ec, address, data); +} +static int +acpi_ec_polling_read ( + union acpi_ec *ec, + u8 address, + u32 *data) +{ + acpi_status status = AE_OK; + int result = 0; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_read"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->polling.lock, flags); + + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + acpi_hw_low_level_write(8, address, &ec->common.data_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (result) + goto end; + + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", + *data, address)); + +end: + spin_unlock_irqrestore(&ec->polling.lock, flags); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + + +static int +acpi_ec_polling_write ( + union acpi_ec *ec, + u8 address, + u8 data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_write"); + + if (!ec) + return_VALUE(-EINVAL); + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + spin_lock_irqsave(&ec->polling.lock, flags); + + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + acpi_hw_low_level_write(8, address, &ec->common.data_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + acpi_hw_low_level_write(8, data, &ec->common.data_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); + if (result) + goto end; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", + data, address)); + +end: + spin_unlock_irqrestore(&ec->polling.lock, flags); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} + +static int +acpi_ec_burst_read ( + union acpi_ec *ec, u8 address, u32 *data) { @@ -230,51 +463,51 @@ acpi_ec_read ( retry: *data = 0; - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } WARN_ON(in_interrupt()); - down(&ec->sem); + down(&ec->burst.sem); if(acpi_ec_enter_burst_mode(ec)) goto end; - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status) { goto end; } - acpi_hw_low_level_write(8, address, &ec->data_addr); + acpi_hw_low_level_write(8, address, &ec->common.data_addr); status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto end; } - acpi_hw_low_level_read(8, data, &ec->data_addr); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", *data, address)); end: acpi_ec_leave_burst_mode(ec); - up(&ec->sem); + up(&ec->burst.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); - if(atomic_read(&ec->leaving_burst) == 2){ + if(atomic_read(&ec->burst.leaving_burst) == 2){ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); - while(atomic_read(&ec->pending_gpe)){ + while(atomic_read(&ec->burst.pending_gpe)){ msleep(1); } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto retry; } @@ -283,8 +516,8 @@ end: static int -acpi_ec_write ( - struct acpi_ec *ec, +acpi_ec_burst_write ( + union acpi_ec *ec, u8 address, u8 data) { @@ -297,14 +530,14 @@ acpi_ec_write ( if (!ec) return_VALUE(-EINVAL); retry: - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } WARN_ON(in_interrupt()); - down(&ec->sem); + down(&ec->burst.sem); if(acpi_ec_enter_burst_mode(ec)) goto end; @@ -312,33 +545,33 @@ retry: status = acpi_ec_read_status(ec); if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)){ - acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status) goto end; - acpi_hw_low_level_read(8, &tmp, &ec->data_addr); + acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); if(tmp != 0x90 ) /* Burst ACK byte*/ goto end; } /*Now we are in burst mode*/ - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status){ goto end; } - acpi_hw_low_level_write(8, address, &ec->data_addr); + acpi_hw_low_level_write(8, address, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto end; } - acpi_hw_low_level_write(8, data, &ec->data_addr); + acpi_hw_low_level_write(8, data, &ec->common.data_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (status) goto end; @@ -347,17 +580,17 @@ retry: end: acpi_ec_leave_burst_mode(ec); - up(&ec->sem); + up(&ec->burst.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); - if(atomic_read(&ec->leaving_burst) == 2){ + if(atomic_read(&ec->burst.leaving_burst) == 2){ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); - while(atomic_read(&ec->pending_gpe)){ + while(atomic_read(&ec->burst.pending_gpe)){ msleep(1); } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto retry; } @@ -370,7 +603,7 @@ end: int ec_read(u8 addr, u8 *val) { - struct acpi_ec *ec; + union acpi_ec *ec; int err; u32 temp_data; @@ -393,7 +626,7 @@ EXPORT_SYMBOL(ec_read); int ec_write(u8 addr, u8 val) { - struct acpi_ec *ec; + union acpi_ec *ec; int err; if (!first_ec) @@ -407,10 +640,66 @@ ec_write(u8 addr, u8 val) } EXPORT_SYMBOL(ec_write); - static int acpi_ec_query ( - struct acpi_ec *ec, + union acpi_ec *ec, + u32 *data) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_query(ec, data); + else + return acpi_ec_burst_query(ec, data); +} +static int +acpi_ec_polling_query ( + union acpi_ec *ec, + u32 *data) +{ + int result = 0; + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 glk = 0; + + ACPI_FUNCTION_TRACE("acpi_ec_query"); + + if (!ec || !data) + return_VALUE(-EINVAL); + + *data = 0; + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return_VALUE(-ENODEV); + } + + /* + * Query the EC to find out which _Qxx method we need to evaluate. + * Note that successful completion of the query causes the ACPI_EC_SCI + * bit to be cleared (and thus clearing the interrupt source). + */ + spin_lock_irqsave(&ec->polling.lock, flags); + + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + if (result) + goto end; + + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + if (!*data) + result = -ENODATA; + +end: + spin_unlock_irqrestore(&ec->polling.lock, flags); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return_VALUE(result); +} +static int +acpi_ec_burst_query ( + union acpi_ec *ec, u32 *data) { int status = 0; @@ -422,13 +711,13 @@ acpi_ec_query ( return_VALUE(-EINVAL); *data = 0; - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } - down(&ec->sem); + down(&ec->burst.sem); if(acpi_ec_enter_burst_mode(ec)) goto end; /* @@ -436,28 +725,28 @@ acpi_ec_query ( * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (status){ - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); goto end; } - acpi_hw_low_level_read(8, data, &ec->data_addr); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); if (!*data) status = -ENODATA; end: acpi_ec_leave_burst_mode(ec); - up(&ec->sem); + up(&ec->burst.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); - if(atomic_read(&ec->leaving_burst) == 2){ + if(atomic_read(&ec->burst.leaving_burst) == 2){ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); status = -ENODATA; } return_VALUE(status); @@ -468,7 +757,7 @@ end: Event Management -------------------------------------------------------------------------- */ -struct acpi_ec_query_data { +union acpi_ec_query_data { acpi_handle handle; u8 data; }; @@ -477,7 +766,59 @@ static void acpi_ec_gpe_query ( void *ec_cxt) { - struct acpi_ec *ec = (struct acpi_ec *) ec_cxt; + if (acpi_ec_polling_mode) + acpi_ec_gpe_polling_query(ec_cxt); + else + acpi_ec_gpe_burst_query(ec_cxt); +} + +static void +acpi_ec_gpe_polling_query ( + void *ec_cxt) +{ + union acpi_ec *ec = (union acpi_ec *) ec_cxt; + u32 value = 0; + unsigned long flags = 0; + static char object_name[5] = {'_','Q','0','0','\0'}; + const char hex[] = {'0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F'}; + + ACPI_FUNCTION_TRACE("acpi_ec_gpe_query"); + + if (!ec_cxt) + goto end; + + spin_lock_irqsave(&ec->polling.lock, flags); + acpi_hw_low_level_read(8, &value, &ec->common.command_addr); + spin_unlock_irqrestore(&ec->polling.lock, flags); + + /* TBD: Implement asynch events! + * NOTE: All we care about are EC-SCI's. Other EC events are + * handled via polling (yuck!). This is because some systems + * treat EC-SCIs as level (versus EDGE!) triggered, preventing + * a purely interrupt-driven approach (grumble, grumble). + */ + if (!(value & ACPI_EC_FLAG_SCI)) + goto end; + + if (acpi_ec_query(ec, &value)) + goto end; + + object_name[2] = hex[((value >> 4) & 0x0F)]; + object_name[3] = hex[(value & 0x0F)]; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); + + acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); + +end: + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); +} +static void +acpi_ec_gpe_burst_query ( + void *ec_cxt) +{ + union acpi_ec *ec = (union acpi_ec *) ec_cxt; u32 value; int result = -ENODATA; static char object_name[5] = {'_','Q','0','0','\0'}; @@ -497,58 +838,87 @@ acpi_ec_gpe_query ( ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); - acpi_evaluate_object(ec->handle, object_name, NULL, NULL); + acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); end: - atomic_dec(&ec->pending_gpe); + atomic_dec(&ec->burst.pending_gpe); return; } static u32 acpi_ec_gpe_handler ( void *data) +{ + if (acpi_ec_polling_mode) + return acpi_ec_gpe_polling_handler(data); + else + return acpi_ec_gpe_burst_handler(data); +} +static u32 +acpi_ec_gpe_polling_handler ( + void *data) +{ + acpi_status status = AE_OK; + union acpi_ec *ec = (union acpi_ec *) data; + + if (!ec) + return ACPI_INTERRUPT_NOT_HANDLED; + + acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); + + status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + acpi_ec_gpe_query, ec); + + if (status == AE_OK) + return ACPI_INTERRUPT_HANDLED; + else + return ACPI_INTERRUPT_NOT_HANDLED; +} +static u32 +acpi_ec_gpe_burst_handler ( + void *data) { acpi_status status = AE_OK; u32 value; - struct acpi_ec *ec = (struct acpi_ec *) data; + union acpi_ec *ec = (union acpi_ec *) data; if (!ec) return ACPI_INTERRUPT_NOT_HANDLED; - acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR); + acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); value = acpi_ec_read_status(ec); if((value & ACPI_EC_FLAG_IBF) && !(value & ACPI_EC_FLAG_BURST) && - (atomic_read(&ec->leaving_burst) == 0)) { + (atomic_read(&ec->burst.leaving_burst) == 0)) { /* * the embedded controller disables * burst mode for any reason other * than the burst disable command * to process critical event. */ - atomic_set(&ec->leaving_burst , 2); /* block current pending transaction + atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction and retry */ - wake_up(&ec->wait); + wake_up(&ec->burst.wait); }else { - if ((ec->expect_event == ACPI_EC_EVENT_OBF && + if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF && (value & ACPI_EC_FLAG_OBF)) || - (ec->expect_event == ACPI_EC_EVENT_IBE && + (ec->burst.expect_event == ACPI_EC_EVENT_IBE && !(value & ACPI_EC_FLAG_IBF))) { - ec->expect_event = 0; - wake_up(&ec->wait); + ec->burst.expect_event = 0; + wake_up(&ec->burst.wait); return ACPI_INTERRUPT_HANDLED; } } if (value & ACPI_EC_FLAG_SCI){ - atomic_add(1, &ec->pending_gpe) ; + atomic_add(1, &ec->burst.pending_gpe) ; status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_ec_gpe_query, ec); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } @@ -585,7 +955,7 @@ acpi_ec_space_handler ( void *region_context) { int result = 0; - struct acpi_ec *ec = NULL; + union acpi_ec *ec = NULL; u64 temp = *value; acpi_integer f_v = 0; int i = 0; @@ -600,7 +970,7 @@ acpi_ec_space_handler ( return_VALUE(AE_BAD_PARAMETER); } - ec = (struct acpi_ec *) handler_context; + ec = (union acpi_ec *) handler_context; next_byte: switch (function) { @@ -661,7 +1031,7 @@ static struct proc_dir_entry *acpi_ec_dir; static int acpi_ec_read_info (struct seq_file *seq, void *offset) { - struct acpi_ec *ec = (struct acpi_ec *) seq->private; + union acpi_ec *ec = (union acpi_ec *) seq->private; ACPI_FUNCTION_TRACE("acpi_ec_read_info"); @@ -669,12 +1039,12 @@ acpi_ec_read_info (struct seq_file *seq, void *offset) goto end; seq_printf(seq, "gpe bit: 0x%02x\n", - (u32) ec->gpe_bit); + (u32) ec->common.gpe_bit); seq_printf(seq, "ports: 0x%02x, 0x%02x\n", - (u32) ec->status_addr.address, (u32) ec->data_addr.address); + (u32) ec->common.status_addr.address, (u32) ec->common.data_addr.address); seq_printf(seq, "use global lock: %s\n", - ec->global_lock?"yes":"no"); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + ec->common.global_lock?"yes":"no"); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); end: return_VALUE(0); @@ -697,7 +1067,7 @@ static int acpi_ec_add_fs ( struct acpi_device *device) { - struct proc_dir_entry *entry; + struct proc_dir_entry *entry = NULL; ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); @@ -744,13 +1114,82 @@ acpi_ec_remove_fs ( Driver Interface -------------------------------------------------------------------------- */ + static int -acpi_ec_add ( +acpi_ec_polling_add ( struct acpi_device *device) { - int result; - acpi_status status; - struct acpi_ec *ec; + int result = 0; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; + unsigned long uid; + + ACPI_FUNCTION_TRACE("acpi_ec_add"); + + if (!device) + return_VALUE(-EINVAL); + + ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + if (!ec) + return_VALUE(-ENOMEM); + memset(ec, 0, sizeof(union acpi_ec)); + + ec->common.handle = device->handle; + ec->common.uid = -1; + spin_lock_init(&ec->polling.lock); + strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_EC_CLASS); + acpi_driver_data(device) = ec; + + /* Use the global lock for all EC transactions? */ + acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); + + /* If our UID matches the UID for the ECDT-enumerated EC, + we now have the *real* EC info, so kill the makeshift one.*/ + acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); + if (ec_ecdt && ec_ecdt->common.uid == uid) { + acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); + + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); + + kfree(ec_ecdt); + } + + /* Get GPE bit assignment (EC events). */ + /* TODO: Add support for _GPE returning a package */ + status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error obtaining GPE bit assignment\n")); + result = -ENODEV; + goto end; + } + + result = acpi_ec_add_fs(device); + if (result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", + acpi_device_name(device), acpi_device_bid(device), + (u32) ec->common.gpe_bit); + + if (!first_ec) + first_ec = device; + +end: + if (result) + kfree(ec); + + return_VALUE(result); +} +static int +acpi_ec_burst_add ( + struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; unsigned long uid; ACPI_FUNCTION_TRACE("acpi_ec_add"); @@ -758,39 +1197,39 @@ acpi_ec_add ( if (!device) return_VALUE(-EINVAL); - ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec) return_VALUE(-ENOMEM); - memset(ec, 0, sizeof(struct acpi_ec)); - - ec->handle = device->handle; - ec->uid = -1; - atomic_set(&ec->pending_gpe, 0); - atomic_set(&ec->leaving_burst , 1); - init_MUTEX(&ec->sem); - init_waitqueue_head(&ec->wait); + memset(ec, 0, sizeof(union acpi_ec)); + + ec->common.handle = device->handle; + ec->common.uid = -1; + atomic_set(&ec->burst.pending_gpe, 0); + atomic_set(&ec->burst.leaving_burst , 1); + init_MUTEX(&ec->burst.sem); + init_waitqueue_head(&ec->burst.wait); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; /* Use the global lock for all EC transactions? */ - acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock); + acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); /* If our UID matches the UID for the ECDT-enumerated EC, we now have the *real* EC info, so kill the makeshift one.*/ - acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid); - if (ec_ecdt && ec_ecdt->uid == uid) { + acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); + if (ec_ecdt && ec_ecdt->common.uid == uid) { acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); - acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); kfree(ec_ecdt); } /* Get GPE bit assignment (EC events). */ /* TODO: Add support for _GPE returning a package */ - status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit); + status = acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, &ec->common.gpe_bit); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error obtaining GPE bit assignment\n")); @@ -804,7 +1243,7 @@ acpi_ec_add ( printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", acpi_device_name(device), acpi_device_bid(device), - (u32) ec->gpe_bit); + (u32) ec->common.gpe_bit); if (!first_ec) first_ec = device; @@ -822,7 +1261,7 @@ acpi_ec_remove ( struct acpi_device *device, int type) { - struct acpi_ec *ec; + union acpi_ec *ec = NULL; ACPI_FUNCTION_TRACE("acpi_ec_remove"); @@ -844,7 +1283,7 @@ acpi_ec_io_ports ( struct acpi_resource *resource, void *context) { - struct acpi_ec *ec = (struct acpi_ec *) context; + union acpi_ec *ec = (union acpi_ec *) context; struct acpi_generic_address *addr; if (resource->id != ACPI_RSTYPE_IO) { @@ -856,10 +1295,10 @@ acpi_ec_io_ports ( * the second address region returned is the status/command * port. */ - if (ec->data_addr.register_bit_width == 0) { - addr = &ec->data_addr; - } else if (ec->command_addr.register_bit_width == 0) { - addr = &ec->command_addr; + if (ec->common.data_addr.register_bit_width == 0) { + addr = &ec->common.data_addr; + } else if (ec->common.command_addr.register_bit_width == 0) { + addr = &ec->common.command_addr; } else { return AE_CTRL_TERMINATE; } @@ -877,8 +1316,8 @@ static int acpi_ec_start ( struct acpi_device *device) { - acpi_status status; - struct acpi_ec *ec; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; ACPI_FUNCTION_TRACE("acpi_ec_start"); @@ -893,35 +1332,36 @@ acpi_ec_start ( /* * Get I/O port addresses. Convert to GAS format. */ - status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS, + status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec); - if (ACPI_FAILURE(status) || ec->command_addr.register_bit_width == 0) { + if (ACPI_FAILURE(status) || ec->common.command_addr.register_bit_width == 0) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error getting I/O port addresses")); return_VALUE(-ENODEV); } - ec->status_addr = ec->command_addr; + ec->common.status_addr = ec->common.command_addr; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", - (u32) ec->gpe_bit, (u32) ec->command_addr.address, - (u32) ec->data_addr.address)); + (u32) ec->common.gpe_bit, (u32) ec->common.command_addr.address, + (u32) ec->common.data_addr.address)); + /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec->gpe_bit, + status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); if (ACPI_FAILURE(status)) { return_VALUE(-ENODEV); } - acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type (NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe (NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - status = acpi_install_address_space_handler (ec->handle, + status = acpi_install_address_space_handler (ec->common.handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, &acpi_ec_space_setup, ec); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); + acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); return_VALUE(-ENODEV); } @@ -934,8 +1374,8 @@ acpi_ec_stop ( struct acpi_device *device, int type) { - acpi_status status; - struct acpi_ec *ec; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; ACPI_FUNCTION_TRACE("acpi_ec_stop"); @@ -944,12 +1384,12 @@ acpi_ec_stop ( ec = acpi_driver_data(device); - status = acpi_remove_address_space_handler(ec->handle, + status = acpi_remove_address_space_handler(ec->common.handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); - status = acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler); + status = acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); @@ -963,26 +1403,76 @@ acpi_fake_ecdt_callback ( void *context, void **retval) { + + if (acpi_ec_polling_mode) + return acpi_fake_ecdt_polling_callback(handle, + Level, context, retval); + else + return acpi_fake_ecdt_burst_callback(handle, + Level, context, retval); +} + +static acpi_status __init +acpi_fake_ecdt_polling_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval) +{ + acpi_status status; + + status = acpi_walk_resources(handle, METHOD_NAME__CRS, + acpi_ec_io_ports, ec_ecdt); + if (ACPI_FAILURE(status)) + return status; + ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; + + ec_ecdt->common.uid = -1; + acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); + + status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); + if (ACPI_FAILURE(status)) + return status; + spin_lock_init(&ec_ecdt->polling.lock); + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.handle = handle; + + printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", + (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, + (u32) ec_ecdt->common.data_addr.address); + + return AE_CTRL_TERMINATE; +} + +static acpi_status __init +acpi_fake_ecdt_burst_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval) +{ acpi_status status; + init_MUTEX(&ec_ecdt->burst.sem); + init_waitqueue_head(&ec_ecdt->burst.wait); status = acpi_walk_resources(handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec_ecdt); if (ACPI_FAILURE(status)) return status; - ec_ecdt->status_addr = ec_ecdt->command_addr; + ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; - ec_ecdt->uid = -1; - acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); + ec_ecdt->common.uid = -1; + acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); - status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->gpe_bit); + status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec_ecdt->common.gpe_bit); if (ACPI_FAILURE(status)) return status; - ec_ecdt->global_lock = TRUE; - ec_ecdt->handle = handle; + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.handle = handle; printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", - (u32) ec_ecdt->gpe_bit, (u32) ec_ecdt->command_addr.address, - (u32) ec_ecdt->data_addr.address); + (u32) ec_ecdt->common.gpe_bit, (u32) ec_ecdt->common.command_addr.address, + (u32) ec_ecdt->common.data_addr.address); return AE_CTRL_TERMINATE; } @@ -1005,12 +1495,12 @@ acpi_ec_fake_ecdt(void) printk(KERN_INFO PREFIX "Try to make an fake ECDT\n"); - ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec_ecdt) { ret = -ENOMEM; goto error; } - memset(ec_ecdt, 0, sizeof(struct acpi_ec)); + memset(ec_ecdt, 0, sizeof(union acpi_ec)); status = acpi_get_devices (ACPI_EC_HID, acpi_fake_ecdt_callback, @@ -1030,6 +1520,60 @@ error: static int __init acpi_ec_get_real_ecdt(void) +{ + if (acpi_ec_polling_mode) + return acpi_ec_polling_get_real_ecdt(); + else + return acpi_ec_burst_get_real_ecdt(); +} + +static int __init +acpi_ec_polling_get_real_ecdt(void) +{ + acpi_status status; + struct acpi_table_ecdt *ecdt_ptr; + + status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) &ecdt_ptr); + if (ACPI_FAILURE(status)) + return -ENODEV; + + printk(KERN_INFO PREFIX "Found ECDT\n"); + + /* + * Generate a temporary ec context to use until the namespace is scanned + */ + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + if (!ec_ecdt) + return -ENOMEM; + memset(ec_ecdt, 0, sizeof(union acpi_ec)); + + ec_ecdt->common.command_addr = ecdt_ptr->ec_control; + ec_ecdt->common.status_addr = ecdt_ptr->ec_control; + ec_ecdt->common.data_addr = ecdt_ptr->ec_data; + ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; + spin_lock_init(&ec_ecdt->polling.lock); + /* use the GL just to be safe */ + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.uid = ecdt_ptr->uid; + + status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); + if (ACPI_FAILURE(status)) { + goto error; + } + + return 0; +error: + printk(KERN_ERR PREFIX "Could not use ECDT\n"); + kfree(ec_ecdt); + ec_ecdt = NULL; + + return -ENODEV; +} + + +static int __init +acpi_ec_burst_get_real_ecdt(void) { acpi_status status; struct acpi_table_ecdt *ecdt_ptr; @@ -1044,22 +1588,22 @@ acpi_ec_get_real_ecdt(void) /* * Generate a temporary ec context to use until the namespace is scanned */ - ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec_ecdt) return -ENOMEM; - memset(ec_ecdt, 0, sizeof(struct acpi_ec)); - - init_MUTEX(&ec_ecdt->sem); - init_waitqueue_head(&ec_ecdt->wait); - ec_ecdt->command_addr = ecdt_ptr->ec_control; - ec_ecdt->status_addr = ecdt_ptr->ec_control; - ec_ecdt->data_addr = ecdt_ptr->ec_data; - ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; + memset(ec_ecdt, 0, sizeof(union acpi_ec)); + + init_MUTEX(&ec_ecdt->burst.sem); + init_waitqueue_head(&ec_ecdt->burst.wait); + ec_ecdt->common.command_addr = ecdt_ptr->ec_control; + ec_ecdt->common.status_addr = ecdt_ptr->ec_control; + ec_ecdt->common.data_addr = ecdt_ptr->ec_data; + ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; /* use the GL just to be safe */ - ec_ecdt->global_lock = TRUE; - ec_ecdt->uid = ecdt_ptr->uid; + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.uid = ecdt_ptr->uid; - status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); + status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); if (ACPI_FAILURE(status)) { goto error; } @@ -1092,20 +1636,20 @@ acpi_ec_ecdt_probe (void) /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit, + status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec_ecdt); if (ACPI_FAILURE(status)) { goto error; } - acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type (NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe (NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR); status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, &acpi_ec_space_setup, ec_ecdt); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); goto error; } @@ -1123,7 +1667,7 @@ error: static int __init acpi_ec_init (void) { - int result; + int result = 0; ACPI_FUNCTION_TRACE("acpi_ec_init"); @@ -1167,3 +1711,10 @@ static int __init acpi_fake_ecdt_setup(char *str) return 0; } __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); +static int __init acpi_ec_set_polling_mode(char *str) +{ + acpi_ec_polling_mode = EC_POLLING; + acpi_ec_driver.ops.add = acpi_ec_polling_add; + return 0; +} +__setup("ec_polling", acpi_ec_set_polling_mode); -- cgit v1.2.3 From 4b31e77455b868b43e665edceb111c9a330c8e0f Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 18 May 2005 13:49:00 -0400 Subject: [ACPI] Always set P-state on initialization Otherwise a platform that supports ACPI based cpufreq and boots up at lowest possible speed could stay there forever. This because the governor may request max speed, but the code doesn't update if there is no change in speed, and it assumed the initial state of max speed. http://bugzilla.kernel.org/show_bug.cgi?id=4634 Signed-off-by: Dominik Brodowski Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 963e17aa205d..60a9e54dd20e 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -442,6 +442,13 @@ acpi_cpufreq_cpu_init ( (u32) data->acpi_data.states[i].transition_latency); cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); + + /* + * the first call to ->target() should result in us actually + * writing something to the appropriate registers. + */ + data->resume = 1; + return (result); err_freqfree: -- cgit v1.2.3 From 90158b83204842c0108d744326868d91cc9c4dfd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 24 Jul 2005 14:22:00 -0400 Subject: [ACPI] fix resume issues on Asus L5D http://bugzilla.kernel.org/show_bug.cgi?id=4416 Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/net/sk98lin/skge.c | 63 +++++++++++++++++++++++++++++++++++++++++++ drivers/pcmcia/yenta_socket.c | 9 +++++++ sound/pci/intel8x0.c | 6 ++++- 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 05b827f79f54..7bfaef9305b2 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -5134,6 +5134,67 @@ static void __devexit skge_remove_one(struct pci_dev *pdev) kfree(pAC); } +#ifdef CONFIG_PM +static int skge_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + struct net_device *otherdev = pAC->dev[1]; + + if (pNet->Up) { + pAC->WasIfUp[0] = SK_TRUE; + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ + } + if (otherdev != dev) { + pNet = netdev_priv(otherdev); + if (pNet->Up) { + pAC->WasIfUp[1] = SK_TRUE; + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */ + } + } + + pci_save_state(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + if (pAC->AllocFlag & SK_ALLOC_IRQ) { + free_irq(dev->irq, dev); + } + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int skge_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_device(pdev); + pci_set_master(pdev); + if (pAC->GIni.GIMacsFound == 2) + request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); + else + request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); + + if (pAC->WasIfUp[0] == SK_TRUE) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 0); /* first device */ + } + if (pAC->dev[1] != dev && pAC->WasIfUp[1] == SK_TRUE) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 1); /* first device */ + } + + return 0; +} +#endif + static struct pci_device_id skge_pci_tbl[] = { { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, @@ -5159,6 +5220,8 @@ static struct pci_driver skge_driver = { .id_table = skge_pci_tbl, .probe = skge_probe_one, .remove = __devexit_p(skge_remove_one), + .suspend = skge_suspend, + .resume = skge_resume, }; static int __init skge_init(void) diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index caf7159a54be..a8a9d954bcf4 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1034,6 +1034,8 @@ static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); pci_disable_device(dev); + free_irq(dev->irq, socket); + /* * Some laptops (IBM T22) do not like us putting the Cardbus * bridge into D3. At a guess, some other laptop will @@ -1059,6 +1061,13 @@ static int yenta_dev_resume (struct pci_dev *dev) pci_enable_device(dev); pci_set_master(dev); + if (socket->cb_irq) + if (request_irq(socket->cb_irq, yenta_interrupt, + SA_SHIRQ, "yenta", socket)) { + printk(KERN_WARNING "Yenta: request_irq() failed on resume!\n"); + socket->cb_irq = 0; + } + if (socket->type && socket->type->restore_state) socket->type->restore_state(socket); } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 8b33b12fa5dc..2a7e63b5757f 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2367,6 +2367,8 @@ static int intel8x0_suspend(snd_card_t *card, pm_message_t state) for (i = 0; i < 3; i++) if (chip->ac97[i]) snd_ac97_suspend(chip->ac97[i]); + if (chip->irq >= 0) + free_irq(chip->irq, (void *)chip); pci_disable_device(chip->pci); return 0; } @@ -2378,7 +2380,9 @@ static int intel8x0_resume(snd_card_t *card) pci_enable_device(chip->pci); pci_set_master(chip->pci); - snd_intel8x0_chip_init(chip, 0); + request_irq(chip->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip); + synchronize_irq(chip->irq); + snd_intel8x0_chip_init(chip, 1); /* refill nocache */ if (chip->fix_nocache) -- cgit v1.2.3 From 68ac767686fd72f37a25bb4895fb4ab0080ba755 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Mon, 25 Apr 2005 14:38:00 -0400 Subject: [ACPI] delete boot-time printk()s from processor_idle.c http://bugzilla.kernel.org/show_bug.cgi?id=4401 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 3702725db97a..fd5458947851 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -768,7 +768,6 @@ static void acpi_processor_power_verify_c3( } if (pr->flags.bm_check) { - printk("Disabling BM access before entering C3\n"); /* bus mastering control is necessary */ if (!pr->flags.bm_control) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -776,7 +775,6 @@ static void acpi_processor_power_verify_c3( return_VOID; } } else { - printk("Invalidating cache before entering C3\n"); /* * WBINVD should be set in fadt, for C3 state to be * supported on when bm_check is not required. -- cgit v1.2.3 From 87bec66b9691522414862dd8d41e430b063735ef Mon Sep 17 00:00:00 2001 From: David Shaohua Li Date: Wed, 27 Jul 2005 23:02:00 -0400 Subject: [ACPI] suspend/resume ACPI PCI Interrupt Links Add reference count and disable ACPI PCI Interrupt Link when no device still uses it. Warn when drivers have not released Link at suspend time. http://bugzilla.kernel.org/show_bug.cgi?id=3469 Signed-off-by: David Shaohua Li Signed-off-by: Len Brown --- arch/i386/pci/acpi.c | 1 + arch/i386/pci/common.c | 6 +++ arch/i386/pci/irq.c | 1 + arch/i386/pci/pci.h | 1 + drivers/acpi/pci_irq.c | 85 +++++++++++++++++++++++++----------- drivers/acpi/pci_link.c | 103 +++++++++++++++++++++++++++++++++++++------- include/acpi/acpi_drivers.h | 3 +- include/linux/acpi.h | 4 -- 8 files changed, 157 insertions(+), 47 deletions(-) diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c index 2db65ec45dc3..42913f43feb0 100644 --- a/arch/i386/pci/acpi.c +++ b/arch/i386/pci/acpi.c @@ -30,6 +30,7 @@ static int __init pci_acpi_init(void) acpi_irq_penalty_init(); pcibios_scanned++; pcibios_enable_irq = acpi_pci_irq_enable; + pcibios_disable_irq = acpi_pci_irq_disable; if (pci_routeirq) { /* diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 720975e1af50..751e49bda180 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -249,3 +249,9 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return pcibios_enable_irq(dev); } + +void pcibios_disable_device (struct pci_dev *dev) +{ + if (pcibios_disable_irq) + pcibios_disable_irq(dev); +} diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index d21b3a2dc978..66e4149ef189 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -56,6 +56,7 @@ struct irq_router_handler { }; int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; +void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL; /* * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index a8fc80ca69f3..dc442dfcab9e 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h @@ -72,3 +72,4 @@ extern int pcibios_scanned; extern spinlock_t pci_config_lock; extern int (*pcibios_enable_irq)(struct pci_dev *dev); +extern void (*pcibios_disable_irq)(struct pci_dev *dev); diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 8093f2e00321..c536ccfc5413 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -269,7 +269,51 @@ acpi_pci_irq_del_prt (int segment, int bus) /* -------------------------------------------------------------------------- PCI Interrupt Routing Support -------------------------------------------------------------------------- */ +typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **); +static int +acpi_pci_allocate_irq(struct acpi_prt_entry *entry, + int *edge_level, + int *active_high_low, + char **link) +{ + int irq; + + ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq"); + + if (entry->link.handle) { + irq = acpi_pci_link_allocate_irq(entry->link.handle, + entry->link.index, edge_level, active_high_low, link); + if (irq < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); + return_VALUE(-1); + } + } else { + irq = entry->link.index; + *edge_level = ACPI_LEVEL_SENSITIVE; + *active_high_low = ACPI_ACTIVE_LOW; + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); + return_VALUE(irq); +} + +static int +acpi_pci_free_irq(struct acpi_prt_entry *entry, + int *edge_level, + int *active_high_low, + char **link) +{ + int irq; + + ACPI_FUNCTION_TRACE("acpi_pci_free_irq"); + if (entry->link.handle) { + irq = acpi_pci_link_free_irq(entry->link.handle); + } else { + irq = entry->link.index; + } + return_VALUE(irq); +} /* * acpi_pci_irq_lookup * success: return IRQ >= 0 @@ -282,12 +326,13 @@ acpi_pci_irq_lookup ( int pin, int *edge_level, int *active_high_low, - char **link) + char **link, + irq_lookup_func func) { struct acpi_prt_entry *entry = NULL; int segment = pci_domain_nr(bus); int bus_nr = bus->number; - int irq; + int ret; ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); @@ -301,22 +346,8 @@ acpi_pci_irq_lookup ( return_VALUE(-1); } - if (entry->link.handle) { - irq = acpi_pci_link_get_irq(entry->link.handle, - entry->link.index, edge_level, active_high_low, link); - if (irq < 0) { - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); - return_VALUE(-1); - } - } else { - irq = entry->link.index; - *edge_level = ACPI_LEVEL_SENSITIVE; - *active_high_low = ACPI_ACTIVE_LOW; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); - - return_VALUE(irq); + ret = func(entry, edge_level, active_high_low, link); + return_VALUE(ret); } /* @@ -330,7 +361,8 @@ acpi_pci_irq_derive ( int pin, int *edge_level, int *active_high_low, - char **link) + char **link, + irq_lookup_func func) { struct pci_dev *bridge = dev; int irq = -1; @@ -363,7 +395,7 @@ acpi_pci_irq_derive ( } irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), - pin, edge_level, active_high_low, link); + pin, edge_level, active_high_low, link, func); } if (irq < 0) { @@ -415,7 +447,7 @@ acpi_pci_irq_enable ( * values override any BIOS-assigned IRQs set during boot. */ irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, - &edge_level, &active_high_low, &link); + &edge_level, &active_high_low, &link, acpi_pci_allocate_irq); /* * If no PRT entry was found, we'll try to derive an IRQ from the @@ -423,7 +455,7 @@ acpi_pci_irq_enable ( */ if (irq < 0) irq = acpi_pci_irq_derive(dev, pin, &edge_level, - &active_high_low, &link); + &active_high_low, &link, acpi_pci_allocate_irq); /* * No IRQ known to the ACPI subsystem - maybe the BIOS / @@ -461,7 +493,9 @@ acpi_pci_irq_enable ( EXPORT_SYMBOL(acpi_pci_irq_enable); -#ifdef CONFIG_ACPI_DEALLOCATE_IRQ +/* FIXME: implement x86/x86_64 version */ +void __attribute__((weak)) acpi_unregister_gsi(u32 i) {} + void acpi_pci_irq_disable ( struct pci_dev *dev) @@ -488,14 +522,14 @@ acpi_pci_irq_disable ( * First we check the PCI IRQ routing table (PRT) for an IRQ. */ gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, - &edge_level, &active_high_low, NULL); + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ if (gsi < 0) gsi = acpi_pci_irq_derive(dev, pin, - &edge_level, &active_high_low, NULL); + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); if (gsi < 0) return_VOID; @@ -511,4 +545,3 @@ acpi_pci_irq_disable ( return_VOID; } -#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */ diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 6ad0e77df9b3..6a29610edc11 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -68,6 +68,10 @@ static struct acpi_driver acpi_pci_link_driver = { }, }; +/* + * If a link is initialized, we never change its active and initialized + * later even the link is disable. Instead, we just repick the active irq + */ struct acpi_pci_link_irq { u8 active; /* Current IRQ */ u8 edge_level; /* All IRQs */ @@ -76,8 +80,7 @@ struct acpi_pci_link_irq { u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; u8 initialized:1; - u8 suspend_resume:1; - u8 reserved:6; + u8 reserved:7; }; struct acpi_pci_link { @@ -85,12 +88,14 @@ struct acpi_pci_link { struct acpi_device *device; acpi_handle handle; struct acpi_pci_link_irq irq; + int refcnt; }; static struct { int count; struct list_head entries; } acpi_link; +DECLARE_MUTEX(acpi_link_lock); /* -------------------------------------------------------------------------- @@ -532,12 +537,12 @@ static int acpi_pci_link_allocate( ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); - if (link->irq.suspend_resume) { - acpi_pci_link_set(link, link->irq.active); - link->irq.suspend_resume = 0; - } - if (link->irq.initialized) + if (link->irq.initialized) { + if (link->refcnt == 0) + /* This means the link is disabled but initialized */ + acpi_pci_link_set(link, link->irq.active); return_VALUE(0); + } /* * search for active IRQ in list of possible IRQs. @@ -596,13 +601,13 @@ static int acpi_pci_link_allocate( } /* - * acpi_pci_link_get_irq + * acpi_pci_link_allocate_irq * success: return IRQ >= 0 * failure: return -1 */ int -acpi_pci_link_get_irq ( +acpi_pci_link_allocate_irq ( acpi_handle handle, int index, int *edge_level, @@ -613,7 +618,7 @@ acpi_pci_link_get_irq ( struct acpi_device *device = NULL; struct acpi_pci_link *link = NULL; - ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq"); + ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq"); result = acpi_bus_get_device(handle, &device); if (result) { @@ -633,21 +638,70 @@ acpi_pci_link_get_irq ( return_VALUE(-1); } - if (acpi_pci_link_allocate(link)) + down(&acpi_link_lock); + if (acpi_pci_link_allocate(link)) { + up(&acpi_link_lock); return_VALUE(-1); + } if (!link->irq.active) { + up(&acpi_link_lock); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); return_VALUE(-1); } + link->refcnt ++; + up(&acpi_link_lock); if (edge_level) *edge_level = link->irq.edge_level; if (active_high_low) *active_high_low = link->irq.active_high_low; if (name) *name = acpi_device_bid(link->device); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Link %s is referenced\n", acpi_device_bid(link->device))); return_VALUE(link->irq.active); } +/* + * We don't change link's irq information here. After it is reenabled, we + * continue use the info + */ +int +acpi_pci_link_free_irq(acpi_handle handle) +{ + struct acpi_device *device = NULL; + struct acpi_pci_link *link = NULL; + acpi_status result; + + ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq"); + + result = acpi_bus_get_device(handle, &device); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n")); + return_VALUE(-1); + } + link = (struct acpi_pci_link *) acpi_driver_data(device); + if (!link) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + return_VALUE(-1); + } + + down(&acpi_link_lock); + if (!link->irq.initialized) { + up(&acpi_link_lock); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n")); + return_VALUE(-1); + } + + link->refcnt --; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Link %s is dereferenced\n", acpi_device_bid(link->device))); + + if (link->refcnt == 0) { + acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); + } + up(&acpi_link_lock); + return_VALUE(link->irq.active); +} /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -677,6 +731,7 @@ acpi_pci_link_add ( strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); acpi_driver_data(device) = link; + down(&acpi_link_lock); result = acpi_pci_link_get_possible(link); if (result) goto end; @@ -712,6 +767,7 @@ acpi_pci_link_add ( end: /* disable all links -- to be activated on use */ acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); + up(&acpi_link_lock); if (result) kfree(link); @@ -726,19 +782,32 @@ irqrouter_suspend( { struct list_head *node = NULL; struct acpi_pci_link *link = NULL; + int ret = 0; ACPI_FUNCTION_TRACE("irqrouter_suspend"); list_for_each(node, &acpi_link.entries) { link = list_entry(node, struct acpi_pci_link, node); if (!link) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Invalid link context\n")); continue; } - if (link->irq.active && link->irq.initialized) - link->irq.suspend_resume = 1; + if (link->irq.initialized && link->refcnt != 0 + /* We ignore legacy IDE device irq */ + && link->irq.active != 14 && link->irq.active !=15) { + printk(KERN_WARNING PREFIX + "%d drivers with interrupt %d neglected to call" + " pci_disable_device at .suspend\n", + link->refcnt, + link->irq.active); + printk(KERN_WARNING PREFIX + "Fix the driver, or rmmod before suspend\n"); + link->refcnt = 0; + ret = -EINVAL; + } } - return_VALUE(0); + return_VALUE(ret); } @@ -756,8 +825,9 @@ acpi_pci_link_remove ( link = (struct acpi_pci_link *) acpi_driver_data(device); - /* TBD: Acquire/release lock */ + down(&acpi_link_lock); list_del(&link->node); + up(&acpi_link_lock); kfree(link); @@ -849,6 +919,7 @@ int __init acpi_irq_balance_set(char *str) __setup("acpi_irq_balance", acpi_irq_balance_set); +/* FIXME: we will remove this interface after all drivers call pci_disable_device */ static struct sysdev_class irqrouter_sysdev_class = { set_kset_name("irqrouter"), .suspend = irqrouter_suspend, diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index e00d9289201b..13f092977c0c 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -56,8 +56,9 @@ /* ACPI PCI Interrupt Link (pci_link.c) */ int acpi_irq_penalty_init (void); -int acpi_pci_link_get_irq (acpi_handle handle, int index, int *edge_level, +int acpi_pci_link_allocate_irq (acpi_handle handle, int index, int *edge_level, int *active_high_low, char **name); +int acpi_pci_link_free_irq(acpi_handle handle); /* ACPI PCI Interrupt Routing (pci_irq.c) */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9c14959bcfa0..ca0cd240cee0 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -440,9 +440,7 @@ int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); * If this matches the last registration, any IRQ resources for gsi * are freed. */ -#ifdef CONFIG_ACPI_DEALLOCATE_IRQ void acpi_unregister_gsi (u32 gsi); -#endif #ifdef CONFIG_ACPI_PCI @@ -467,9 +465,7 @@ struct pci_dev; int acpi_pci_irq_enable (struct pci_dev *dev); void acpi_penalize_isa_irq(int irq, int active); -#ifdef CONFIG_ACPI_DEALLOCATE_IRQ void acpi_pci_irq_disable (struct pci_dev *dev); -#endif struct acpi_pci_driver { struct acpi_pci_driver *next; -- cgit v1.2.3 From 7cd7ae531c7896f90485ce6ebb2b1370a0a7d8c8 Mon Sep 17 00:00:00 2001 From: Linda Xie Date: Fri, 15 Jul 2005 17:49:27 -0500 Subject: [SCSI] scsi/ibmvscsi/srp.h: Fix a wrong type code used for SRP_LOGIN_REJ This patch fixes srp.h which uses 0x80 for SRP_LOGIN_REJ instead of 0xc2. Signed-off-by: Linda Xie Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/srp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h index 2ae5154fd89c..7d8e4c4accb9 100644 --- a/drivers/scsi/ibmvscsi/srp.h +++ b/drivers/scsi/ibmvscsi/srp.h @@ -35,7 +35,7 @@ enum srp_types { SRP_LOGIN_REQ_TYPE = 0x00, SRP_LOGIN_RSP_TYPE = 0xC0, - SRP_LOGIN_REJ_TYPE = 0x80, + SRP_LOGIN_REJ_TYPE = 0xC2, SRP_I_LOGOUT_TYPE = 0x03, SRP_T_LOGOUT_TYPE = 0x80, SRP_TSK_MGMT_TYPE = 0x01, -- cgit v1.2.3 From e572f7cc28a0b01b96ede3f78f448ad55c5e67ad Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 27 Jul 2005 01:07:43 -0700 Subject: [SCSI] fc4 warning fix drivers/fc4/fc.c: In function `fcp_scsi_dev_reset': drivers/fc4/fc.c:933: warning: control reaches end of non-void function Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/fc4/fc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index 5d961f5e0ca0..e4710d1d1f9d 100644 --- a/drivers/fc4/fc.c +++ b/drivers/fc4/fc.c @@ -1004,8 +1004,8 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt) return FAILED; } fc->rst_pkt->eh_state = SCSI_STATE_UNUSED; - return SUCCESS; #endif + return SUCCESS; } static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) -- cgit v1.2.3 From f7ff898ad3971cd36967453d331c57d97d407007 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 30 Jul 2005 10:37:55 -0500 Subject: [SCSI] aic7xxx: fix bug in DT handing Basically DT isn't reported or handled at all. The problem is that lines of code like this: spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ; don't do what you think they do when spi_dt is a single bit variable. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 116d0f51ca2c..d0d0b84a31f4 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1635,9 +1635,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel, spi_period(starget) = tinfo->curr.period; spi_width(starget) = tinfo->curr.width; spi_offset(starget) = tinfo->curr.offset; - spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ; - spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ; - spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ; + spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0; + spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0; + spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0; spi_display_xfer_agreement(starget); break; } @@ -2435,8 +2435,10 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) if (dt) { period = 9; /* 12.5ns is the only period valid for DT */ ppr_options |= MSG_EXT_PPR_DT_REQ; - } else if (period == 9) + } else if (period == 9) { period = 10; /* if resetting DT, period must be >= 25ns */ + ppr_options &= ~MSG_EXT_PPR_DT_REQ; + } ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); -- cgit v1.2.3 From 141d751e264c16db554f6681d84056ebde0e8078 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 29 Jul 2005 22:59:16 -0700 Subject: [PATCH] ppc32: inotify syscalls Add inotify system call stubs to PPC32. Signed-off-by: Robert Love Acked-by: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/kernel/misc.S | 3 +++ include/asm-ppc/unistd.h | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 191a8def3bdb..c2fb85b49a11 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -1451,3 +1451,6 @@ _GLOBAL(sys_call_table) .long sys_waitid .long sys_ioprio_set .long sys_ioprio_get + .long sys_inotify_init /* 275 */ + .long sys_inotify_add_watch + .long sys_inotify_rm_watch diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h index a7894e0fbbb1..3173ab3d2eb9 100644 --- a/include/asm-ppc/unistd.h +++ b/include/asm-ppc/unistd.h @@ -279,8 +279,11 @@ #define __NR_waitid 272 #define __NR_ioprio_set 273 #define __NR_ioprio_get 274 +#define __NR_inotify_init 275 +#define __NR_inotify_add_watch 276 +#define __NR_inotify_rm_watch 277 -#define __NR_syscalls 275 +#define __NR_syscalls 278 #define __NR(n) #n -- cgit v1.2.3 From 5fa918b451f625870cd4275ca908b2392ee86a51 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 29 Jul 2005 22:59:17 -0700 Subject: [PATCH] ppc64: inotify syscalls inotify system call support for PPC64 [ I don't think we need sys32 compatibility versions--and if we do, I failed in life. ] Signed-off-by: Robert Love Acked-by: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/misc.S | 6 ++++++ include/asm-ppc64/unistd.h | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 59f4f9973818..a05b50b738e9 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -1129,6 +1129,9 @@ _GLOBAL(sys_call_table32) .llong .compat_sys_waitid .llong .sys32_ioprio_set .llong .sys32_ioprio_get + .llong .sys_inotify_init /* 275 */ + .llong .sys_inotify_add_watch + .llong .sys_inotify_rm_watch .balign 8 _GLOBAL(sys_call_table) @@ -1407,3 +1410,6 @@ _GLOBAL(sys_call_table) .llong .sys_waitid .llong .sys_ioprio_set .llong .sys_ioprio_get + .llong .sys_inotify_init /* 275 */ + .llong .sys_inotify_add_watch + .llong .sys_inotify_rm_watch diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h index 4a94acf6bfed..977bc980c1af 100644 --- a/include/asm-ppc64/unistd.h +++ b/include/asm-ppc64/unistd.h @@ -285,8 +285,11 @@ #define __NR_waitid 272 #define __NR_ioprio_set 273 #define __NR_ioprio_get 274 +#define __NR_inotify_init 275 +#define __NR_inotify_add_watch 276 +#define __NR_inotify_rm_watch 277 -#define __NR_syscalls 275 +#define __NR_syscalls 278 #ifdef __KERNEL__ #define NR_syscalls __NR_syscalls #endif -- cgit v1.2.3 From e310fd43256b3cf4d37f6447b8f7413ca744657a Mon Sep 17 00:00:00 2001 From: "Martin J. Bligh" Date: Fri, 29 Jul 2005 22:59:18 -0700 Subject: [PATCH] Fix NUMA node sizing in nr_free_zone_pages We are iterating over all nodes in nr_free_zone_pages(). Because the fallback zonelists contain all nodes in the system, and we walk all the zonelists, we're counting memory multiple times (once for each node). This caused us to make a size estimate of 32GB for an 8GB AMD64 box, which makes all the dirty ratio calculations, etc incorrect. There's still a further bug to fix from e820 holes causing overestimation as well, but this fix is separate, and good as is, and fixes one class of problems. Problem found by Badari, and tested by Ram Pai - thanks! Signed-off-by: Martin J. Bligh Signed-off-by: Matt Dobson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 42bccfb8464d..8d088371196a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1061,20 +1061,19 @@ unsigned int nr_free_pages_pgdat(pg_data_t *pgdat) static unsigned int nr_free_zone_pages(int offset) { - pg_data_t *pgdat; + /* Just pick one node, since fallback list is circular */ + pg_data_t *pgdat = NODE_DATA(numa_node_id()); unsigned int sum = 0; - for_each_pgdat(pgdat) { - struct zonelist *zonelist = pgdat->node_zonelists + offset; - struct zone **zonep = zonelist->zones; - struct zone *zone; + struct zonelist *zonelist = pgdat->node_zonelists + offset; + struct zone **zonep = zonelist->zones; + struct zone *zone; - for (zone = *zonep++; zone; zone = *zonep++) { - unsigned long size = zone->present_pages; - unsigned long high = zone->pages_high; - if (size > high) - sum += size - high; - } + for (zone = *zonep++; zone; zone = *zonep++) { + unsigned long size = zone->present_pages; + unsigned long high = zone->pages_high; + if (size > high) + sum += size - high; } return sum; -- cgit v1.2.3 From 5ce17b18e16177dd6409dabd38df5c2c9b58fc2d Mon Sep 17 00:00:00 2001 From: Eugene Surovegin Date: Fri, 29 Jul 2005 22:59:19 -0700 Subject: [PATCH] ppc32: fix 44x early serial debug for configurations with more than 512M of RAM Fix 44x early serial debugging for big RAM configurations (more than 512M). We cannot use default OpenBIOS virtual mapping, because it interferes with pinned TLB entry. While we are at it, move early UART mapping to TLB slot 0, so it can survive longer during boot process (slot 1 is used by the first ioremap call, effectively killing UART mapping if it occupies this slot). Also, change UART TLB entry size to 4K (256M is too much for a bunch of registers :). Squash some warnings on the way. Tested on Ebony and Ocotea with 1G of RAM. Thanks to Scott Coulter for diagnosing this problem. Signed-off-by: Eugene Surovegin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/kernel/head_44x.S | 12 ++++++------ arch/ppc/platforms/4xx/ebony.c | 6 +++++- arch/ppc/platforms/4xx/ebony.h | 13 +++++++++++-- arch/ppc/platforms/4xx/ocotea.c | 4 ++++ arch/ppc/platforms/4xx/ocotea.h | 13 +++++++++++-- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 6c7ae6052464..72ee8f33bde4 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -179,14 +179,14 @@ skpinv: addi r4,r4,1 /* Increment */ 4: #ifdef CONFIG_SERIAL_TEXT_DEBUG /* - * Add temporary UART mapping for early debug. This - * mapping must be identical to that used by the early - * bootloader code since the same asm/serial.h parameters - * are used for polled operation. + * Add temporary UART mapping for early debug. + * We can map UART registers wherever we want as long as they don't + * interfere with other system mappings (e.g. with pinned entries). + * For an example of how we handle this - see ocotea.h. --ebs */ /* pageid fields */ lis r3,UART0_IO_BASE@h - ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M + ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K /* xlat fields */ lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */ @@ -196,7 +196,7 @@ skpinv: addi r4,r4,1 /* Increment */ li r5,0 ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G) - li r0,1 /* TLB slot 1 */ + li r0,0 /* TLB slot 0 */ tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index cd11734ef7c5..509e69a095f0 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -7,7 +7,7 @@ * Copyright 2002-2005 MontaVista Software Inc. * * Eugene Surovegin or - * Copyright (c) 2003, 2004 Zultys Technologies + * Copyright (c) 2003-2005 Zultys Technologies * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -248,6 +249,9 @@ ebony_early_serial_map(void) #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) /* Configure debug serial access */ gen550_init(0, &port); + + /* Purge TLB entry added in head_44x.S for early serial access */ + _tlbie(UART0_IO_BASE); #endif port.membase = ioremap64(PPC440GP_UART1_ADDR, 8); diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h index 47c391c9174d..d08faa46a0ae 100644 --- a/arch/ppc/platforms/4xx/ebony.h +++ b/arch/ppc/platforms/4xx/ebony.h @@ -56,9 +56,18 @@ * Serial port defines */ -/* OpenBIOS defined UART mappings, used before early_serial_setup */ +#if defined(__BOOTER__) +/* OpenBIOS defined UART mappings, used by bootloader shim */ #define UART0_IO_BASE 0xE0000200 #define UART1_IO_BASE 0xE0000300 +#else +/* head_44x.S created UART mapping, used before early_serial_setup. + * We cannot use default OpenBIOS UART mappings because they + * don't work for configurations with more than 512M RAM. --ebs + */ +#define UART0_IO_BASE 0xF0000200 +#define UART1_IO_BASE 0xF0000300 +#endif /* external Epson SG-615P */ #define BASE_BAUD 691200 @@ -66,7 +75,7 @@ #define STD_UART_OP(num) \ { 0, BASE_BAUD, 0, UART##num##_INT, \ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ - iomem_base: UART##num##_IO_BASE, \ + iomem_base: (void*)UART##num##_IO_BASE, \ io_type: SERIAL_IO_MEM}, #define SERIAL_PORT_DFNS \ diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 5f82a6bc7046..8fc34a344769 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -266,6 +267,9 @@ ocotea_early_serial_map(void) #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) /* Configure debug serial access */ gen550_init(0, &port); + + /* Purge TLB entry added in head_44x.S for early serial access */ + _tlbie(UART0_IO_BASE); #endif port.membase = ioremap64(PPC440GX_UART1_ADDR, 8); diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h index 202dc8251190..33251153ac5f 100644 --- a/arch/ppc/platforms/4xx/ocotea.h +++ b/arch/ppc/platforms/4xx/ocotea.h @@ -55,15 +55,24 @@ */ #define RS_TABLE_SIZE 2 -/* OpenBIOS defined UART mappings, used before early_serial_setup */ +#if defined(__BOOTER__) +/* OpenBIOS defined UART mappings, used by bootloader shim */ #define UART0_IO_BASE 0xE0000200 #define UART1_IO_BASE 0xE0000300 +#else +/* head_44x.S created UART mapping, used before early_serial_setup. + * We cannot use default OpenBIOS UART mappings because they + * don't work for configurations with more than 512M RAM. --ebs + */ +#define UART0_IO_BASE 0xF0000200 +#define UART1_IO_BASE 0xF0000300 +#endif #define BASE_BAUD 11059200/16 #define STD_UART_OP(num) \ { 0, BASE_BAUD, 0, UART##num##_INT, \ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ - iomem_base: UART##num##_IO_BASE, \ + iomem_base: (void*)UART##num##_IO_BASE, \ io_type: SERIAL_IO_MEM}, #define SERIAL_PORT_DFNS \ -- cgit v1.2.3 From 92ed0223aefa795d1873427e25599cb70b2148ee Mon Sep 17 00:00:00 2001 From: Dave Peterson Date: Fri, 29 Jul 2005 22:59:20 -0700 Subject: [PATCH] x86_64: fix bug in csum_partial_copy_generic() I was observing reproducible crashes on the "movw %bx,(%rsi)" instruction below while a process in a recvfrom() system call was copying packet data to user space. The patch below fixes the exception table and causes the crash to no longer reproduce. Please apply. Acked-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/lib/csum-copy.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86_64/lib/csum-copy.S b/arch/x86_64/lib/csum-copy.S index 01808ec37836..72fd55ee896e 100644 --- a/arch/x86_64/lib/csum-copy.S +++ b/arch/x86_64/lib/csum-copy.S @@ -188,8 +188,8 @@ csum_partial_copy_generic: source movw (%rdi),%bx adcl %ebx,%eax - dest decl %ecx + dest movw %bx,(%rsi) leaq 2(%rdi),%rdi leaq 2(%rsi),%rsi -- cgit v1.2.3 From d7a465b4740806e4ee34061ad455595b2fa9fad5 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Fri, 29 Jul 2005 22:59:21 -0700 Subject: [PATCH] vesafb: Document mtrr boot option usage Document mtrr boot option usage to Documentation/fb/vesafb.txt. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/fb/vesafb.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/fb/vesafb.txt b/Documentation/fb/vesafb.txt index 814e2f56a6ad..62db6758d1c1 100644 --- a/Documentation/fb/vesafb.txt +++ b/Documentation/fb/vesafb.txt @@ -144,7 +144,21 @@ vgapal Use the standard vga registers for palette changes. This is the default. pmipal Use the protected mode interface for palette changes. -mtrr setup memory type range registers for the vesafb framebuffer. +mtrr:n setup memory type range registers for the vesafb framebuffer + where n: + 0 - disabled (equivalent to nomtrr) + 1 - uncachable + 2 - write-back + 3 - write-combining (default) + 4 - write-through + + If you see the following in dmesg, choose the type that matches the + old one. In this example, use "mtrr:2". +... +mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining +... + +nomtrr disable mtrr vremap:n remap 'n' MiB of video RAM. If 0 or not specified, remap memory -- cgit v1.2.3 From c70f5d6610c601ea2ae4ae4e49f66c80801e895f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 30 Jul 2005 10:22:49 -0700 Subject: [PATCH] revert bogus softirq changes This snuck in with an x86_64 change. Thanks to Richard Purdie for spotting it. Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/softirq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/softirq.c b/kernel/softirq.c index 31007d6542cc..b4ab6af1dea8 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -86,7 +86,7 @@ restart: /* Reset the pending bitmask before enabling irqs */ local_softirq_pending() = 0; - //local_irq_enable(); + local_irq_enable(); h = softirq_vec; @@ -99,7 +99,7 @@ restart: pending >>= 1; } while (pending); - //local_irq_disable(); + local_irq_disable(); pending = local_softirq_pending(); if (pending && --max_restart) -- cgit v1.2.3 From 6a1caa21d66bcb9ba9892435a0a54fc32cd9eeab Mon Sep 17 00:00:00 2001 From: "Natalie.Protasevich@unisys.com" Date: Sat, 30 Jul 2005 11:25:32 -0700 Subject: [PATCH] x86_64: avoid wasting IRQs patch update The patch adds boundary check for the MAX_GSI_NUM. Same as the update for i386, the patch addresses a problem with ACPI SCI IRQ. The patch corrects the code such that SCI IRQ is skipped and duplicate entry is avoided. The VIA chipset uses 4-bit IRQ register for internal interrupt routing, and therefore cannot handle IRQ numbers assigned to its devices. The patch corrects this problem by allowing PCI IRQs below 16. Signed-off-by: Natalie Protasevich Acked-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/mpparse.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index 08abf9f5b159..79c362d03e2e 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c @@ -970,8 +970,21 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low) * due to unused I/O APIC pins. */ int irq = gsi; - gsi = pci_irq++; - gsi_to_irq[irq] = gsi; + if (gsi < MAX_GSI_NUM) { + if (gsi > 15) + gsi = pci_irq++; +#ifdef CONFIG_ACPI_BUS + /* + * Don't assign IRQ used by ACPI SCI + */ + if (gsi == acpi_fadt.sci_int) + gsi = pci_irq++; +#endif + gsi_to_irq[irq] = gsi; + } else { + printk(KERN_ERR "GSI %u is too high\n", gsi); + return gsi; + } } io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, -- cgit v1.2.3 From 035a4a4f8976bdf12aab992c630d3a6cfba90ea8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 30 Jul 2005 13:12:18 -0700 Subject: [PATCH] sk98lin: basic suspend/resume support fixes An early version of the sk98lin patch was merged via Len's tree. But there were subsequent updates as a result of review from Jeff. THis fixes things up. Signed-off-by: Rafael J. Wysocki Cc: Jeff Garzik Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/sk98lin/skge.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 074521a36341..49bd8c7c3f7d 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -5141,17 +5141,18 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state) SK_AC *pAC = pNet->pAC; struct net_device *otherdev = pAC->dev[1]; - if (pNet->Up) { - pAC->WasIfUp[0] = SK_TRUE; + if (netif_running(dev)) { + netif_carrier_off(dev); DoPrintInterfaceChange = SK_FALSE; SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ + netif_device_detach(dev); } if (otherdev != dev) { - pNet = netdev_priv(otherdev); - if (pNet->Up) { - pAC->WasIfUp[1] = SK_TRUE; + if (netif_running(otherdev)) { + netif_carrier_off(otherdev); DoPrintInterfaceChange = SK_FALSE; SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */ + netif_device_detach(otherdev); } } @@ -5171,23 +5172,36 @@ static int skge_resume(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); DEV_NET *pNet = netdev_priv(dev); SK_AC *pAC = pNet->pAC; + struct net_device *otherdev = pAC->dev[1]; + int ret; pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); pci_enable_device(pdev); pci_set_master(pdev); if (pAC->GIni.GIMacsFound == 2) - request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); + ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); else - request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); + ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); + if (ret) { + printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq); + pAC->AllocFlag &= ~SK_ALLOC_IRQ; + dev->irq = 0; + pci_disable_device(pdev); + return -EBUSY; + } - if (pAC->WasIfUp[0] == SK_TRUE) { + netif_device_attach(dev); + if (netif_running(dev)) { DoPrintInterfaceChange = SK_FALSE; SkDrvInitAdapter(pAC, 0); /* first device */ - } - if (pAC->dev[1] != dev && pAC->WasIfUp[1] == SK_TRUE) { - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAC, 1); /* first device */ + } + if (otherdev != dev) { + netif_device_attach(otherdev); + if (netif_running(otherdev)) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 1); /* second device */ + } } return 0; -- cgit v1.2.3 From 889371f61fd5bb914d0331268f12432590cf7e85 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 30 Jul 2005 13:41:56 -0700 Subject: Revert "yenta free_irq on suspend" ACPI is wrong. Devices should not release their IRQ's on suspend and re-aquire them on resume. ACPI should just re-init the IRQ controller instead of breaking most drivers very subtly. Breakage reported by Hugh Dickins Undo: d8c4b4195c7d664baf296818bf756775149232d3 Signed-off-by: Linus Torvalds --- drivers/pcmcia/yenta_socket.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 744e469a9eda..6837491f021c 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1107,8 +1107,6 @@ static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) pci_read_config_dword(dev, 17*4, &socket->saved_state[1]); pci_disable_device(dev); - free_irq(dev->irq, socket); - /* * Some laptops (IBM T22) do not like us putting the Cardbus * bridge into D3. At a guess, some other laptop will @@ -1134,13 +1132,6 @@ static int yenta_dev_resume (struct pci_dev *dev) pci_enable_device(dev); pci_set_master(dev); - if (socket->cb_irq) - if (request_irq(socket->cb_irq, yenta_interrupt, - SA_SHIRQ, "yenta", socket)) { - printk(KERN_WARNING "Yenta: request_irq() failed on resume!\n"); - socket->cb_irq = 0; - } - if (socket->type && socket->type->restore_state) socket->type->restore_state(socket); } -- cgit v1.2.3 From d1b04c081e3fb0a08ac108737e4efa9f4830c916 Mon Sep 17 00:00:00 2001 From: Baruch Even Date: Sat, 30 Jul 2005 17:41:59 -0700 Subject: [NET]: Spelling mistakes threshoulds -> thresholds Just simple spelling mistake fixes. Signed-Off-By: Baruch Even Signed-off-by: David S. Miller --- include/net/tcp.h | 2 +- net/ipv4/ipmr.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index f4f9aba07ac2..5010f0c5a56e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1236,7 +1236,7 @@ static inline void tcp_sync_left_out(struct tcp_sock *tp) tp->left_out = tp->sacked_out + tp->lost_out; } -/* Set slow start threshould and cwnd not falling to slow start */ +/* Set slow start threshold and cwnd not falling to slow start */ static inline void __tcp_enter_cwr(struct tcp_sock *tp) { tp->undo_marker = 0; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 7833d920bdba..dc806b578427 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -362,7 +362,7 @@ out: /* Fill oifs list. It is called under write locked mrt_lock. */ -static void ipmr_update_threshoulds(struct mfc_cache *cache, unsigned char *ttls) +static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls) { int vifi; @@ -727,7 +727,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) if (c != NULL) { write_lock_bh(&mrt_lock); c->mfc_parent = mfc->mfcc_parent; - ipmr_update_threshoulds(c, mfc->mfcc_ttls); + ipmr_update_thresholds(c, mfc->mfcc_ttls); if (!mrtsock) c->mfc_flags |= MFC_STATIC; write_unlock_bh(&mrt_lock); @@ -744,7 +744,7 @@ static int ipmr_mfc_add(struct mfcctl *mfc, int mrtsock) c->mfc_origin=mfc->mfcc_origin.s_addr; c->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr; c->mfc_parent=mfc->mfcc_parent; - ipmr_update_threshoulds(c, mfc->mfcc_ttls); + ipmr_update_thresholds(c, mfc->mfcc_ttls); if (!mrtsock) c->mfc_flags |= MFC_STATIC; -- cgit v1.2.3 From 1f494c0e040b001cf844280910d04ba7ebdc2898 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 30 Jul 2005 17:44:07 -0700 Subject: [NETFILTER] Inherit masq_index to slave connections masq_index is used for cleanup in case the interface address changes (such as a dialup ppp link with dynamic addreses). Without this patch, slave connections are not evicted in such a case, since they don't inherit masq_index. Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 86f04e41dd8e..a7f0c821a9b2 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -512,6 +512,11 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, conntrack->master = exp->master; #ifdef CONFIG_IP_NF_CONNTRACK_MARK conntrack->mark = exp->master->mark; +#endif +#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ + defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) + /* this is ugly, but there is no other place where to put it */ + conntrack->nat.masq_index = exp->master->nat.masq_index; #endif nf_conntrack_get(&conntrack->master->ct_general); CONNTRACK_STAT_INC(expect_new); -- cgit v1.2.3 From db44575f6fd55df6ff67ddd21f7ad5be5a741136 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sat, 30 Jul 2005 17:46:44 -0700 Subject: [NET]: fix oops after tunnel module unload Tunnel modules used to obtain module refcount each time when some tunnel was created, which meaned that tunnel could be unloaded only after all the tunnels are deleted. Since killing old MOD_*_USE_COUNT macros this protection has gone. It is possible to return it back as module_get/put, but it looks more natural and practically useful to force destruction of all the child tunnels on module unload. Signed-off-by: Alexey Kuznetsov Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 21 ++++++++++++++++++--- net/ipv4/ipip.c | 20 ++++++++++++++++++-- net/ipv6/sit.c | 21 +++++++++++++++++++-- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 884835522224..f0d5740d7e22 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -290,7 +290,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int dev_hold(dev); ipgre_tunnel_link(nt); - /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: @@ -1277,12 +1276,28 @@ err1: goto out; } -static void ipgre_fini(void) +static void __exit ipgre_destroy_tunnels(void) +{ + int prio; + + for (prio = 0; prio < 4; prio++) { + int h; + for (h = 0; h < HASH_SIZE; h++) { + struct ip_tunnel *t; + while ((t = tunnels[prio][h]) != NULL) + unregister_netdevice(t->dev); + } + } +} + +static void __exit ipgre_fini(void) { if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) printk(KERN_INFO "ipgre close: can't remove protocol\n"); - unregister_netdev(ipgre_fb_tunnel_dev); + rtnl_lock(); + ipgre_destroy_tunnels(); + rtnl_unlock(); } module_init(ipgre_init); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index c3947cd566b7..c05c1df0bb04 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -255,7 +255,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c dev_hold(dev); ipip_tunnel_link(nt); - /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: @@ -920,12 +919,29 @@ static int __init ipip_init(void) goto out; } +static void __exit ipip_destroy_tunnels(void) +{ + int prio; + + for (prio = 1; prio < 4; prio++) { + int h; + for (h = 0; h < HASH_SIZE; h++) { + struct ip_tunnel *t; + while ((t = tunnels[prio][h]) != NULL) + unregister_netdevice(t->dev); + } + } +} + static void __exit ipip_fini(void) { if (ipip_unregister() < 0) printk(KERN_INFO "ipip close: can't deregister tunnel\n"); - unregister_netdev(ipip_fb_tunnel_dev); + rtnl_lock(); + ipip_destroy_tunnels(); + unregister_netdevice(ipip_fb_tunnel_dev); + rtnl_unlock(); } module_init(ipip_init); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index b788f55e139b..e553e5b80d6e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -195,7 +195,6 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int dev_hold(dev); ipip6_tunnel_link(nt); - /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: @@ -794,10 +793,28 @@ static struct net_protocol sit_protocol = { .err_handler = ipip6_err, }; +static void __exit sit_destroy_tunnels(void) +{ + int prio; + + for (prio = 1; prio < 4; prio++) { + int h; + for (h = 0; h < HASH_SIZE; h++) { + struct ip_tunnel *t; + while ((t = tunnels[prio][h]) != NULL) + unregister_netdevice(t->dev); + } + } +} + void __exit sit_cleanup(void) { inet_del_protocol(&sit_protocol, IPPROTO_IPV6); - unregister_netdev(ipip6_fb_tunnel_dev); + + rtnl_lock(); + sit_destroy_tunnels(); + unregister_netdevice(ipip6_fb_tunnel_dev); + rtnl_unlock(); } int __init sit_init(void) -- cgit v1.2.3 From f0098f7863f814a5adc0b9cb271605d063cad7fa Mon Sep 17 00:00:00 2001 From: Denis Lunev Date: Sat, 30 Jul 2005 17:47:25 -0700 Subject: [NET] Fix too aggressive backoff in dst garbage collection The bug is evident when it is seen once. dst gc timer was backed off, when gc queue is not empty. But this means that timer quickly backs off, if at least one destination remains in use. Normally, the bug is invisible, because adding new dst entry to queue cancels the backoff. But it shots deadly with destination cache overflow when new destinations are not released for long time f.e. after an interface goes down. The fix is to cancel backoff when something was released. Signed-off-by: Denis Lunev Signed-off-by: Alexey Kuznetsov Signed-off-by: David S. Miller --- net/core/dst.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/net/core/dst.c b/net/core/dst.c index fc434ade5270..334790da9f16 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -45,6 +45,7 @@ static struct timer_list dst_gc_timer = static void dst_run_gc(unsigned long dummy) { int delayed = 0; + int work_performed; struct dst_entry * dst, **dstp; if (!spin_trylock(&dst_lock)) { @@ -52,9 +53,9 @@ static void dst_run_gc(unsigned long dummy) return; } - del_timer(&dst_gc_timer); dstp = &dst_garbage_list; + work_performed = 0; while ((dst = *dstp) != NULL) { if (atomic_read(&dst->__refcnt)) { dstp = &dst->next; @@ -62,6 +63,7 @@ static void dst_run_gc(unsigned long dummy) continue; } *dstp = dst->next; + work_performed = 1; dst = dst_destroy(dst); if (dst) { @@ -86,9 +88,14 @@ static void dst_run_gc(unsigned long dummy) dst_gc_timer_inc = DST_GC_MAX; goto out; } - if ((dst_gc_timer_expires += dst_gc_timer_inc) > DST_GC_MAX) - dst_gc_timer_expires = DST_GC_MAX; - dst_gc_timer_inc += DST_GC_INC; + if (!work_performed) { + if ((dst_gc_timer_expires += dst_gc_timer_inc) > DST_GC_MAX) + dst_gc_timer_expires = DST_GC_MAX; + dst_gc_timer_inc += DST_GC_INC; + } else { + dst_gc_timer_inc = DST_GC_INC; + dst_gc_timer_expires = DST_GC_MIN; + } dst_gc_timer.expires = jiffies + dst_gc_timer_expires; #if RT_CACHE_DEBUG >= 2 printk("dst_total: %d/%d %ld\n", -- cgit v1.2.3 From f6620cab9485d435aa93490533b8268d36dc4526 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:02 -0700 Subject: [PATCH] skge: silence mac data parity messages Using Genesis board, I get harmless error reports. Rather than console error, turn it into a error counter. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 5cacc7ad9e79..1ba0ab596abd 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2633,11 +2633,17 @@ static inline void skge_tx_intr(struct net_device *dev) spin_unlock(&skge->tx_lock); } +/* Parity errors seem to happen when Genesis is connected to a switch + * with no other ports present. Heartbeat error?? + */ static void skge_mac_parity(struct skge_hw *hw, int port) { - printk(KERN_ERR PFX "%s: mac data parity error\n", - hw->dev[port] ? hw->dev[port]->name - : (port == 0 ? "(port A)": "(port B")); + struct net_device *dev = hw->dev[port]; + + if (dev) { + struct skge_port *skge = netdev_priv(dev); + ++skge->net_stats.tx_heartbeat_errors; + } if (hw->chip_id == CHIP_ID_GENESIS) skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), -- cgit v1.2.3 From acdd80d514a08800380c9f92b1bf4d4c9e818125 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:03 -0700 Subject: [PATCH] skge: remove SK-9EE support The SK-9E boards use the Marvell Yukon2 chipset which is not supported by the skge driver. Thanks to Ralph Roesler for noticing. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 1ba0ab596abd..e33645035f68 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -75,7 +75,6 @@ static const struct pci_device_id skge_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ -- cgit v1.2.3 From 0eedf4ac5b536c7922263adf1b1d991d2e2397b9 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:04 -0700 Subject: [PATCH] skge: disable tranmitter on shutdown Here is a fix for a typo, thanks Eliot Dresselhaus. Since transmitter not active when device is down, it wasn't really noticed. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index e33645035f68..3adef3c8797a 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1819,7 +1819,7 @@ static void yukon_stop(struct skge_port *skge) gma_write16(hw, port, GM_GP_CTRL, gma_read16(hw, port, GM_GP_CTRL) - & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA)); + & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); gma_read16(hw, port, GM_GP_CTRL); /* set GPHY Control reset */ -- cgit v1.2.3 From 4ff6ac052b90ee4dfee92f8e2c5cb7ef8a4d8f13 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:05 -0700 Subject: [PATCH] skge: phy lock deadlock Cleanup the phy_lock deadlock because of relocking in the nway_reset path. Reported by Francois Romieu. Also, don't need to do irqsave/restore for blink, just excluding bh is good enough. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 3adef3c8797a..9fa519574203 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -668,14 +668,13 @@ static void skge_blink_timer(unsigned long data) { struct skge_port *skge = (struct skge_port *) data; struct skge_hw *hw = skge->hw; - unsigned long flags; - spin_lock_irqsave(&hw->phy_lock, flags); + spin_lock_bh(&hw->phy_lock); if (skge->blink_on) skge_led_on(hw, skge->port); else skge_led_off(hw, skge->port); - spin_unlock_irqrestore(&hw->phy_lock, flags); + spin_unlock_bh(&hw->phy_lock); skge->blink_on = !skge->blink_on; mod_timer(&skge->led_blink, jiffies + BLINK_HZ); @@ -1208,7 +1207,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) * namely for the 1000baseTX cards that use the XMAC's * GMII mode. */ - spin_lock_bh(&hw->phy_lock); /* Take external Phy out of reset */ r = skge_read32(hw, B2_GP_IO); if (port == 0) @@ -1218,7 +1216,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) skge_write32(hw, B2_GP_IO, r); skge_read32(hw, B2_GP_IO); - spin_unlock_bh(&hw->phy_lock); /* Enable GMII interfac */ xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); @@ -1744,9 +1741,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) gma_write16(hw, port, GM_GP_CTRL, reg); skge_read16(hw, GMAC_IRQ_SRC); - spin_lock_bh(&hw->phy_lock); yukon_init(hw, port); - spin_unlock_bh(&hw->phy_lock); /* MIB clear */ reg = gma_read16(hw, port, GM_PHY_ADDR); @@ -2096,10 +2091,12 @@ static int skge_up(struct net_device *dev) skge_write32(hw, B0_IMSK, hw->intr_mask); /* Initialze MAC */ + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) genesis_mac_init(hw, port); else yukon_mac_init(hw, port); + spin_unlock_bh(&hw->phy_lock); /* Configure RAMbuffers */ chunk = hw->ram_size / ((hw->ports + 1)*2); -- cgit v1.2.3 From 382317138b3ade02c9c319531ab0619e95dbc672 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:06 -0700 Subject: [PATCH] skge: support yukon lite rev 4 The check for Yukon lite changes was restricting itself to rev A3. It turns out that these changes are also true on A4 and later. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 9fa519574203..0857be8f99f2 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1687,7 +1687,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) /* WA code for COMA mode -- set PHY reset */ if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + hw->chip_rev >= CHIP_REV_YU_LITE_A3) skge_write32(hw, B2_GP_IO, (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9)); @@ -1697,7 +1697,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) /* WA code for COMA mode -- clear PHY reset */ if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + hw->chip_rev >= CHIP_REV_YU_LITE_A3) skge_write32(hw, B2_GP_IO, (skge_read32(hw, B2_GP_IO) | GP_DIR_9) & ~GP_IO_9); @@ -1790,7 +1790,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); reg = GMF_OPER_ON | GMF_RX_F_FL_ON; if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + hw->chip_rev >= CHIP_REV_YU_LITE_A3) reg &= ~GMF_RX_F_FL_ON; skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); @@ -1807,7 +1807,7 @@ static void yukon_stop(struct skge_port *skge) int port = skge->port; if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) { + hw->chip_rev >= CHIP_REV_YU_LITE_A3) { skge_write32(hw, B2_GP_IO, skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9); } -- cgit v1.2.3 From 2c66851460c9438823e39b76887376d1511fb67c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:07 -0700 Subject: [PATCH] skge: whitespace fixes Minor whitespace cleanups. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 6 +++--- drivers/net/skge.h | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 0857be8f99f2..6b04b89cbb4f 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -248,7 +248,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else { u32 setting; - switch(ecmd->speed) { + switch (ecmd->speed) { case SPEED_1000: if (ecmd->duplex == DUPLEX_FULL) setting = SUPPORTED_1000baseT_Full; @@ -1026,7 +1026,7 @@ static void bcom_check_link(struct skge_hw *hw, int port) } /* Check Duplex mismatch */ - switch(aux & PHY_B_AS_AN_RES_MSK) { + switch (aux & PHY_B_AS_AN_RES_MSK) { case PHY_B_RES_1000FD: skge->duplex = DUPLEX_FULL; break; @@ -1097,7 +1097,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) r |= XM_MMU_NO_PRE; xm_write16(hw, port, XM_MMU_CMD,r); - switch(id1) { + switch (id1) { case PHY_BCOM_ID1_C0: /* * Workaround BCOM Errata for the C0 type. diff --git a/drivers/net/skge.h b/drivers/net/skge.h index fced3d2bc072..2086809f4b03 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -1509,7 +1509,7 @@ enum { PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ }; -#define PHY_M_LED_PULS_DUR(x) ( ((x)<<12) & PHY_M_LEDC_PULS_MSK) +#define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK) enum { PULS_NO_STR = 0,/* no pulse stretching */ @@ -1522,7 +1522,7 @@ enum { PULS_1300MS = 7,/* 1.3 s to 2.7 s */ }; -#define PHY_M_LED_BLINK_RT(x) ( ((x)<<8) & PHY_M_LEDC_BL_R_MSK) +#define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK) enum { BLINK_42MS = 0,/* 42 ms */ @@ -1602,9 +1602,9 @@ enum { PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ }; -#define PHY_M_FELP_LED2_CTRL(x) ( ((x)<<8) & PHY_M_FELP_LED2_MSK) -#define PHY_M_FELP_LED1_CTRL(x) ( ((x)<<4) & PHY_M_FELP_LED1_MSK) -#define PHY_M_FELP_LED0_CTRL(x) ( ((x)<<0) & PHY_M_FELP_LED0_MSK) +#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK) +#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK) +#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK) enum { LED_PAR_CTRL_COLX = 0x00, @@ -1640,7 +1640,7 @@ enum { PHY_M_MAC_MD_COPPER = 5,/* Copper only */ PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */ }; -#define PHY_M_MAC_MODE_SEL(x) ( ((x)<<7) & PHY_M_MAC_MD_MSK) +#define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK) /***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ enum { @@ -1650,10 +1650,10 @@ enum { PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ }; -#define PHY_M_LEDC_LOS_CTRL(x) ( ((x)<<12) & PHY_M_LEDC_LOS_MSK) -#define PHY_M_LEDC_INIT_CTRL(x) ( ((x)<<8) & PHY_M_LEDC_INIT_MSK) -#define PHY_M_LEDC_STA1_CTRL(x) ( ((x)<<4) & PHY_M_LEDC_STA1_MSK) -#define PHY_M_LEDC_STA0_CTRL(x) ( ((x)<<0) & PHY_M_LEDC_STA0_MSK) +#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK) +#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK) +#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK) +#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK) /* GMAC registers */ /* Port Registers */ -- cgit v1.2.3 From d8a09943ebbaca9befd995d8fe10dd9885256dbf Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:08 -0700 Subject: [PATCH] skge: fifo control register access fix The code to clear fifo errors was incorrect and sending garbage to the external phy. Removed the no longer used inline's funcs. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 17 ++++++++++------- drivers/net/skge.h | 11 ----------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 6b04b89cbb4f..f50405b4fba2 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1818,8 +1818,8 @@ static void yukon_stop(struct skge_port *skge) gma_read16(hw, port, GM_GP_CTRL); /* set GPHY Control reset */ - gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET); - gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET); + skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); + skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); } static void yukon_get_stats(struct skge_port *skge, u64 *data) @@ -1850,11 +1850,12 @@ static void yukon_mac_intr(struct skge_hw *hw, int port) if (status & GM_IS_RX_FF_OR) { ++skge->net_stats.rx_fifo_errors; - gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO); + skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); } + if (status & GM_IS_TX_FF_UR) { ++skge->net_stats.tx_fifo_errors; - gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU); + skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); } } @@ -1898,12 +1899,14 @@ static void yukon_link_down(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; + u16 ctrl; pr_debug("yukon_link_down\n"); gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); - gm_phy_write(hw, port, GM_GP_CTRL, - gm_phy_read(hw, port, GM_GP_CTRL) - & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)); + + ctrl = gma_read16(hw, port, GM_GP_CTRL); + ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); + gma_write16(hw, port, GM_GP_CTRL, ctrl); if (skge->flow_control == FLOW_MODE_REM_SEND) { /* restore Asymmetric Pause bit */ diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 2086809f4b03..e2546950bf55 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2606,17 +2606,6 @@ static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v) skge_write16(hw, SK_GMAC_REG(port,r), v); } -static inline void gma_write32(const struct skge_hw *hw, int port, int r, u32 v) -{ - skge_write16(hw, SK_GMAC_REG(port, r), (u16) v); - skge_write32(hw, SK_GMAC_REG(port, r+4), (u16)(v >> 16)); -} - -static inline void gma_write8(const struct skge_hw *hw, int port, int r, u8 v) -{ - skge_write8(hw, SK_GMAC_REG(port,r), v); -} - static inline void gma_set_addr(struct skge_hw *hw, int port, int reg, const u8 *addr) { -- cgit v1.2.3 From 4cde06ed0fb58402ec1d6d117122d1058983a393 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:09 -0700 Subject: [PATCH] skge: ignore phy interrupts during negotiation During autonegotiation set PHY interrupt mask to ignore bogus speed change interrupts. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 6 +++--- drivers/net/skge.h | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index f50405b4fba2..43a275d97107 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1660,9 +1660,9 @@ static void yukon_init(struct skge_hw *hw, int port) /* Enable phy interrupt on autonegotiation complete (or link up) */ if (skge->autoneg == AUTONEG_ENABLE) - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK); else - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); } static void yukon_reset(struct skge_hw *hw, int port) @@ -1891,7 +1891,7 @@ static void yukon_link_up(struct skge_port *skge) reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; gma_write16(hw, port, GM_GP_CTRL, reg); - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); skge_link_up(skge); } diff --git a/drivers/net/skge.h b/drivers/net/skge.h index e2546950bf55..c37214692c07 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -1449,10 +1449,12 @@ enum { PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */ PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */ PHY_M_IS_JABBER = 1<<0, /* Jabber */ -}; -#define PHY_M_DEF_MSK ( PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | \ - PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR) + PHY_M_IS_DEF_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | + PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR, + + PHY_M_IS_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL, +}; /***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ enum { -- cgit v1.2.3 From 6abebb538d317ead09cc0f3c2a0752047f9ff961 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:10 -0700 Subject: [PATCH] skge: led toggle cleanup Cleanup code that is used to toggle LED's. Since we get called from ethtool, can use that thread rather than setting up a timer. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 170 +++++++++++++++++++++++------------------------------ drivers/net/skge.h | 2 - 2 files changed, 74 insertions(+), 98 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 43a275d97107..6b889a346a16 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -55,7 +55,7 @@ #define ETH_JUMBO_MTU 9000 #define TX_WATCHDOG (5 * HZ) #define NAPI_WEIGHT 64 -#define BLINK_HZ (HZ/4) +#define BLINK_MS 250 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); MODULE_AUTHOR("Stephen Hemminger "); @@ -619,83 +619,98 @@ static int skge_set_coalesce(struct net_device *dev, return 0; } -static void skge_led_on(struct skge_hw *hw, int port) +enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST }; +static void skge_led(struct skge_port *skge, enum led_mode mode) { + struct skge_hw *hw = skge->hw; + int port = skge->port; + + spin_lock_bh(&hw->phy_lock); if (hw->chip_id == CHIP_ID_GENESIS) { - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); - skge_write8(hw, B0_LED, LED_STAT_ON); + switch (mode) { + case LED_MODE_OFF: + xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); + skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); + break; - skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); - skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); + case LED_MODE_ON: + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); + skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); - /* For Broadcom Phy only */ - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); - } else { - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_ON) | - PHY_M_LED_MO_10(MO_LED_ON) | - PHY_M_LED_MO_100(MO_LED_ON) | - PHY_M_LED_MO_1000(MO_LED_ON) | - PHY_M_LED_MO_RX(MO_LED_ON)); - } -} + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); + skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); -static void skge_led_off(struct skge_hw *hw, int port) -{ - if (hw->chip_id == CHIP_ID_GENESIS) { - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); - skge_write8(hw, B0_LED, LED_STAT_OFF); + break; - skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); + case LED_MODE_TST: + skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); + skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); + skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - /* Broadcom only */ - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); + xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); + break; + } } else { - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_OFF) | - PHY_M_LED_MO_10(MO_LED_OFF) | - PHY_M_LED_MO_100(MO_LED_OFF) | - PHY_M_LED_MO_1000(MO_LED_OFF) | - PHY_M_LED_MO_RX(MO_LED_OFF)); + switch (mode) { + case LED_MODE_OFF: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_DUP(MO_LED_OFF) | + PHY_M_LED_MO_10(MO_LED_OFF) | + PHY_M_LED_MO_100(MO_LED_OFF) | + PHY_M_LED_MO_1000(MO_LED_OFF) | + PHY_M_LED_MO_RX(MO_LED_OFF)); + break; + case LED_MODE_ON: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, + PHY_M_LED_PULS_DUR(PULS_170MS) | + PHY_M_LED_BLINK_RT(BLINK_84MS) | + PHY_M_LEDC_TX_CTRL | + PHY_M_LEDC_DP_CTRL); + + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_RX(MO_LED_OFF) | + (skge->speed == SPEED_100 ? + PHY_M_LED_MO_100(MO_LED_ON) : 0)); + break; + case LED_MODE_TST: + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + PHY_M_LED_MO_DUP(MO_LED_ON) | + PHY_M_LED_MO_10(MO_LED_ON) | + PHY_M_LED_MO_100(MO_LED_ON) | + PHY_M_LED_MO_1000(MO_LED_ON) | + PHY_M_LED_MO_RX(MO_LED_ON)); + } } -} - -static void skge_blink_timer(unsigned long data) -{ - struct skge_port *skge = (struct skge_port *) data; - struct skge_hw *hw = skge->hw; - - spin_lock_bh(&hw->phy_lock); - if (skge->blink_on) - skge_led_on(hw, skge->port); - else - skge_led_off(hw, skge->port); spin_unlock_bh(&hw->phy_lock); - - skge->blink_on = !skge->blink_on; - mod_timer(&skge->led_blink, jiffies + BLINK_HZ); } /* blink LED's for finding board */ static int skge_phys_id(struct net_device *dev, u32 data) { struct skge_port *skge = netdev_priv(dev); + unsigned long ms; + enum led_mode mode = LED_MODE_TST; if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT / HZ) * 1000; + else + ms = data * 1000; - /* start blinking */ - skge->blink_on = 1; - mod_timer(&skge->led_blink, jiffies+1); + while (ms > 0) { + skge_led(skge, mode); + mode ^= LED_MODE_TST; - msleep_interruptible(data * 1000); - del_timer_sync(&skge->led_blink); + if (msleep_interruptible(BLINK_MS)) + break; + ms -= BLINK_MS; + } - skge_led_off(skge->hw, skge->port); + /* back to regular LED state */ + skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); return 0; } @@ -1192,13 +1207,6 @@ static void genesis_mac_init(struct skge_hw *hw, int port) xm_write16(hw, port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* initialize Rx, Tx and Link LED */ - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); - - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); - /* Unreset the XMAC. */ skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); @@ -1565,7 +1573,6 @@ static void yukon_init(struct skge_hw *hw, int port) { struct skge_port *skge = netdev_priv(hw->dev[port]); u16 ctrl, ct1000, adv; - u16 ledctrl, ledover; pr_debug("yukon_init\n"); if (skge->autoneg == AUTONEG_ENABLE) { @@ -1637,27 +1644,6 @@ static void yukon_init(struct skge_hw *hw, int port) gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - /* Setup Phy LED's */ - ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS); - ledover = 0; - - ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; - - /* turn off the Rx LED (LED_RX) */ - ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); - - /* disable blink mode (LED_DUPLEX) on collisions */ - ctrl |= PHY_M_LEDC_DP_CTRL; - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); - - if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) { - /* turn on 100 Mbps LED (LED_LINK100) */ - ledover |= PHY_M_LED_MO_100(MO_LED_ON); - } - - if (ledover) - gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); - /* Enable phy interrupt on autonegotiation complete (or link up) */ if (skge->autoneg == AUTONEG_ENABLE) gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK); @@ -2115,6 +2101,7 @@ static int skge_up(struct net_device *dev) /* Start receiver BMU */ wmb(); skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); + skge_led(skge, LED_MODE_ON); pr_debug("skge_up completed\n"); return 0; @@ -2139,8 +2126,6 @@ static int skge_down(struct net_device *dev) netif_stop_queue(dev); - del_timer_sync(&skge->led_blink); - /* Stop transmitter */ skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), @@ -2174,15 +2159,12 @@ static int skge_down(struct net_device *dev) if (hw->chip_id == CHIP_ID_GENESIS) { skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP); } else { skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); } - /* turn off led's */ - skge_write16(hw, B0_LED, LED_STAT_OFF); + skge_led(skge, LED_MODE_OFF); skge_tx_clean(skge); skge_rx_clean(skge); @@ -3088,10 +3070,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, spin_lock_init(&skge->tx_lock); - init_timer(&skge->led_blink); - skge->led_blink.function = skge_blink_timer; - skge->led_blink.data = (unsigned long) skge; - if (hw->chip_id != CHIP_ID_GENESIS) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; skge->rx_csum = 1; diff --git a/drivers/net/skge.h b/drivers/net/skge.h index c37214692c07..b432f1bb8168 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2507,8 +2507,6 @@ struct skge_port { dma_addr_t dma; unsigned long mem_size; unsigned int rx_buf_size; - - struct timer_list led_blink; }; -- cgit v1.2.3 From f2e1e47d14aae1f33e98cf8d9ea93e2fe9e2f521 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 22 Jul 2005 16:26:11 -0700 Subject: [PATCH] skge: version 0.8 Increase driver version to 0.8 Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 6b889a346a16..f15739481d62 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -42,7 +42,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "0.7" +#define DRV_VERSION "0.8" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 -- cgit v1.2.3 From faa725332f39329288f52b7f872ffda866ba5b09 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 27 Jul 2005 01:06:35 -0700 Subject: [PATCH] SCSI_SATA has to be a tristate SCSI=m must disallow static drivers. The problem is that all the SATA drivers depend on SCSI_SATA. With SCSI=m and SCSI_SATA=y this allows the static enabling of the SATA drivers with unwanted effects, e.g.: - SCSI=m, SCSI_SATA=y, SCSI_ATA_ADMA=y -> SCSI_ATA_ADMA is built statically but scsi/built-in.o is not linked into the kernel - SCSI=m, SCSI_SATA=y, SCSI_ATA_ADMA=y, SCSI_SATA_AHCI=m -> SCSI_ATA_ADMA and libata are built statically but scsi/built-in.o is not linked into the kernel, SCSI_SATA_AHCI is built modular (unresolved symbols due to missing libata) Signed-off-by: Adrian Bunk Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/scsi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 96df148ed969..f1e8c4223ed1 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -424,7 +424,7 @@ config SCSI_IN2000 source "drivers/scsi/megaraid/Kconfig.megaraid" config SCSI_SATA - bool "Serial ATA (SATA) support" + tristate "Serial ATA (SATA) support" depends on SCSI help This driver family supports Serial ATA host controllers -- cgit v1.2.3 From 00354cfb92bd819a0d09d3ef9988e509b6675fdd Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Thu, 21 Jul 2005 12:18:02 -0700 Subject: [PATCH] bonding: documentation update Contains general updates (additional configuration info, hopefully better examples, updated some out of date info, and a bonus pass through ispell to banish the "paramters.") and info specific to gratuitous ARP and xmit policy functionality already in 2.6.13-rc2. Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- Documentation/networking/bonding.txt | 978 ++++++++++++++++++++++++----------- 1 file changed, 677 insertions(+), 301 deletions(-) diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index 0bc2ed136a38..24d029455baa 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -1,5 +1,7 @@ - Linux Ethernet Bonding Driver HOWTO + Linux Ethernet Bonding Driver HOWTO + + Latest update: 21 June 2005 Initial release : Thomas Davis Corrections, HA extensions : 2000/10/03-15 : @@ -11,15 +13,22 @@ Corrections, HA extensions : 2000/10/03-15 : Reorganized and updated Feb 2005 by Jay Vosburgh -Note : ------- +Introduction +============ + + The Linux bonding driver provides a method for aggregating +multiple network interfaces into a single logical "bonded" interface. +The behavior of the bonded interfaces depends upon the mode; generally +speaking, modes provide either hot standby or load balancing services. +Additionally, link integrity monitoring may be performed. -The bonding driver originally came from Donald Becker's beowulf patches for -kernel 2.0. It has changed quite a bit since, and the original tools from -extreme-linux and beowulf sites will not work with this version of the driver. + The bonding driver originally came from Donald Becker's +beowulf patches for kernel 2.0. It has changed quite a bit since, and +the original tools from extreme-linux and beowulf sites will not work +with this version of the driver. -For new versions of the driver, patches for older kernels and the updated -userspace tools, please follow the links at the end of this file. + For new versions of the driver, updated userspace tools, and +who to ask for help, please follow the links at the end of this file. Table of Contents ================= @@ -30,9 +39,13 @@ Table of Contents 3. Configuring Bonding Devices 3.1 Configuration with sysconfig support +3.1.1 Using DHCP with sysconfig +3.1.2 Configuring Multiple Bonds with sysconfig 3.2 Configuration with initscripts support +3.2.1 Using DHCP with initscripts +3.2.2 Configuring Multiple Bonds with initscripts 3.3 Configuring Bonding Manually -3.4 Configuring Multiple Bonds +3.3.1 Configuring Multiple Bonds Manually 5. Querying Bonding Configuration 5.1 Bonding Configuration @@ -56,21 +69,30 @@ Table of Contents 11. Promiscuous mode -12. High Availability Information +12. Configuring Bonding for High Availability 12.1 High Availability in a Single Switch Topology -12.1.1 Bonding Mode Selection for Single Switch Topology -12.1.2 Link Monitoring for Single Switch Topology 12.2 High Availability in a Multiple Switch Topology -12.2.1 Bonding Mode Selection for Multiple Switch Topology -12.2.2 Link Monitoring for Multiple Switch Topology -12.3 Switch Behavior Issues for High Availability +12.2.1 HA Bonding Mode Selection for Multiple Switch Topology +12.2.2 HA Link Monitoring for Multiple Switch Topology + +13. Configuring Bonding for Maximum Throughput +13.1 Maximum Throughput in a Single Switch Topology +13.1.1 MT Bonding Mode Selection for Single Switch Topology +13.1.2 MT Link Monitoring for Single Switch Topology +13.2 Maximum Throughput in a Multiple Switch Topology +13.2.1 MT Bonding Mode Selection for Multiple Switch Topology +13.2.2 MT Link Monitoring for Multiple Switch Topology -13. Hardware Specific Considerations -13.1 IBM BladeCenter +14. Switch Behavior Issues +14.1 Link Establishment and Failover Delays +14.2 Duplicated Incoming Packets -14. Frequently Asked Questions +15. Hardware Specific Considerations +15.1 IBM BladeCenter -15. Resources and Links +16. Frequently Asked Questions + +17. Resources and Links 1. Bonding Driver Installation @@ -86,16 +108,10 @@ the following steps: 1.1 Configure and build the kernel with bonding ----------------------------------------------- - The latest version of the bonding driver is available in the + The current version of the bonding driver is available in the drivers/net/bonding subdirectory of the most recent kernel source -(which is available on http://kernel.org). - - Prior to the 2.4.11 kernel, the bonding driver was maintained -largely outside the kernel tree; patches for some earlier kernels are -available on the bonding sourceforge site, although those patches are -still several years out of date. Most users will want to use either -the most recent kernel from kernel.org or whatever kernel came with -their distro. +(which is available on http://kernel.org). Most users "rolling their +own" will want to use the most recent kernel from kernel.org. Configure kernel with "make menuconfig" (or "make xconfig" or "make config"), then select "Bonding driver support" in the "Network @@ -103,8 +119,8 @@ device support" section. It is recommended that you configure the driver as module since it is currently the only way to pass parameters to the driver or configure more than one bonding device. - Build and install the new kernel and modules, then proceed to -step 2. + Build and install the new kernel and modules, then continue +below to install ifenslave. 1.2 Install ifenslave Control Utility ------------------------------------- @@ -147,9 +163,9 @@ default kernel source include directory. Options for the bonding driver are supplied as parameters to the bonding module at load time. They may be given as command line arguments to the insmod or modprobe command, but are usually specified -in either the /etc/modprobe.conf configuration file, or in a -distro-specific configuration file (some of which are detailed in the -next section). +in either the /etc/modules.conf or /etc/modprobe.conf configuration +file, or in a distro-specific configuration file (some of which are +detailed in the next section). The available bonding driver parameters are listed below. If a parameter is not specified the default value is used. When initially @@ -162,34 +178,34 @@ degradation will occur during link failures. Very few devices do not support at least miimon, so there is really no reason not to use it. Options with textual values will accept either the text name - or, for backwards compatibility, the option value. E.g., - "mode=802.3ad" and "mode=4" set the same mode. +or, for backwards compatibility, the option value. E.g., +"mode=802.3ad" and "mode=4" set the same mode. The parameters are as follows: arp_interval - Specifies the ARP monitoring frequency in milli-seconds. If - ARP monitoring is used in a load-balancing mode (mode 0 or 2), - the switch should be configured in a mode that evenly - distributes packets across all links - such as round-robin. If - the switch is configured to distribute the packets in an XOR + Specifies the ARP link monitoring frequency in milliseconds. + If ARP monitoring is used in an etherchannel compatible mode + (modes 0 and 2), the switch should be configured in a mode + that evenly distributes packets across all links. If the + switch is configured to distribute the packets in an XOR fashion, all replies from the ARP targets will be received on the same link which could cause the other team members to - fail. ARP monitoring should not be used in conjunction with - miimon. A value of 0 disables ARP monitoring. The default + fail. ARP monitoring should not be used in conjunction with + miimon. A value of 0 disables ARP monitoring. The default value is 0. arp_ip_target - Specifies the ip addresses to use when arp_interval is > 0. - These are the targets of the ARP request sent to determine the - health of the link to the targets. Specify these values in - ddd.ddd.ddd.ddd format. Multiple ip adresses must be - seperated by a comma. At least one IP address must be given - for ARP monitoring to function. The maximum number of targets - that can be specified is 16. The default value is no IP - addresses. + Specifies the IP addresses to use as ARP monitoring peers when + arp_interval is > 0. These are the targets of the ARP request + sent to determine the health of the link to the targets. + Specify these values in ddd.ddd.ddd.ddd format. Multiple IP + addresses must be separated by a comma. At least one IP + address must be given for ARP monitoring to function. The + maximum number of targets that can be specified is 16. The + default value is no IP addresses. downdelay @@ -207,11 +223,13 @@ lacp_rate are: slow or 0 - Request partner to transmit LACPDUs every 30 seconds (default) + Request partner to transmit LACPDUs every 30 seconds fast or 1 Request partner to transmit LACPDUs every 1 second + The default is slow. + max_bonds Specifies the number of bonding devices to create for this @@ -221,10 +239,11 @@ max_bonds miimon - Specifies the frequency in milli-seconds that MII link - monitoring will occur. A value of zero disables MII link - monitoring. A value of 100 is a good starting point. The - use_carrier option, below, affects how the link state is + Specifies the MII link monitoring frequency in milliseconds. + This determines how often the link state of each slave is + inspected for link failures. A value of zero disables MII + link monitoring. A value of 100 is a good starting point. + The use_carrier option, below, affects how the link state is determined. See the High Availability section for additional information. The default value is 0. @@ -246,17 +265,31 @@ mode active. A different slave becomes active if, and only if, the active slave fails. The bond's MAC address is externally visible on only one port (network adapter) - to avoid confusing the switch. This mode provides - fault tolerance. The primary option affects the - behavior of this mode. + to avoid confusing the switch. + + In bonding version 2.6.2 or later, when a failover + occurs in active-backup mode, bonding will issue one + or more gratuitous ARPs on the newly active slave. + One gratutious ARP is issued for the bonding master + interface and each VLAN interfaces configured above + it, provided that the interface has at least one IP + address configured. Gratuitous ARPs issued for VLAN + interfaces are tagged with the appropriate VLAN id. + + This mode provides fault tolerance. The primary + option, documented below, affects the behavior of this + mode. balance-xor or 2 - XOR policy: Transmit based on [(source MAC address - XOR'd with destination MAC address) modulo slave - count]. This selects the same slave for each - destination MAC address. This mode provides load - balancing and fault tolerance. + XOR policy: Transmit based on the selected transmit + hash policy. The default policy is a simple [(source + MAC address XOR'd with destination MAC address) modulo + slave count]. Alternate transmit policies may be + selected via the xmit_hash_policy option, described + below. + + This mode provides load balancing and fault tolerance. broadcast or 3 @@ -270,7 +303,17 @@ mode duplex settings. Utilizes all slaves in the active aggregator according to the 802.3ad specification. - Pre-requisites: + Slave selection for outgoing traffic is done according + to the transmit hash policy, which may be changed from + the default simple XOR policy via the xmit_hash_policy + option, documented below. Note that not all transmit + policies may be 802.3ad compliant, particularly in + regards to the packet mis-ordering requirements of + section 43.2.4 of the 802.3ad standard. Differing + peer implementations will have varying tolerances for + noncompliance. + + Prerequisites: 1. Ethtool support in the base drivers for retrieving the speed and duplex of each slave. @@ -333,7 +376,7 @@ mode When a link is reconnected or a new slave joins the bond the receive traffic is redistributed among all - active slaves in the bond by intiating ARP Replies + active slaves in the bond by initiating ARP Replies with the selected mac address to each of the clients. The updelay parameter (detailed below) must be set to a value equal or greater than the switch's @@ -396,6 +439,60 @@ use_carrier 0 will use the deprecated MII / ETHTOOL ioctls. The default value is 1. +xmit_hash_policy + + Selects the transmit hash policy to use for slave selection in + balance-xor and 802.3ad modes. Possible values are: + + layer2 + + Uses XOR of hardware MAC addresses to generate the + hash. The formula is + + (source MAC XOR destination MAC) modulo slave count + + This algorithm will place all traffic to a particular + network peer on the same slave. + + This algorithm is 802.3ad compliant. + + layer3+4 + + This policy uses upper layer protocol information, + when available, to generate the hash. This allows for + traffic to a particular network peer to span multiple + slaves, although a single connection will not span + multiple slaves. + + The formula for unfragmented TCP and UDP packets is + + ((source port XOR dest port) XOR + ((source IP XOR dest IP) AND 0xffff) + modulo slave count + + For fragmented TCP or UDP packets and all other IP + protocol traffic, the source and destination port + information is omitted. For non-IP traffic, the + formula is the same as for the layer2 transmit hash + policy. + + This policy is intended to mimic the behavior of + certain switches, notably Cisco switches with PFC2 as + well as some Foundry and IBM products. + + This algorithm is not fully 802.3ad compliant. A + single TCP or UDP conversation containing both + fragmented and unfragmented packets will see packets + striped across two interfaces. This may result in out + of order delivery. Most traffic types will not meet + this criteria, as TCP rarely fragments traffic, and + most UDP traffic is not involved in extended + conversations. Other implementations of 802.3ad may + or may not tolerate this noncompliance. + + The default value is layer2. This option was added in bonding +version 2.6.3. In earlier versions of bonding, this parameter does +not exist, and the layer2 policy is the only policy. 3. Configuring Bonding Devices @@ -448,8 +545,9 @@ Bonding devices can be managed by hand, however, as follows. slave devices. On SLES 9, this is most easily done by running the yast2 sysconfig configuration utility. The goal is for to create an ifcfg-id file for each slave device. The simplest way to accomplish -this is to configure the devices for DHCP. The name of the -configuration file for each device will be of the form: +this is to configure the devices for DHCP (this is only to get the +file ifcfg-id file created; see below for some issues with DHCP). The +name of the configuration file for each device will be of the form: ifcfg-id-xx:xx:xx:xx:xx:xx @@ -459,7 +557,7 @@ the device's permanent MAC address. Once the set of ifcfg-id-xx:xx:xx:xx:xx:xx files has been created, it is necessary to edit the configuration files for the slave devices (the MAC addresses correspond to those of the slave devices). -Before editing, the file will contain muliple lines, and will look +Before editing, the file will contain multiple lines, and will look something like this: BOOTPROTO='dhcp' @@ -496,16 +594,11 @@ STARTMODE="onboot" BONDING_MASTER="yes" BONDING_MODULE_OPTS="mode=active-backup miimon=100" BONDING_SLAVE0="eth0" -BONDING_SLAVE1="eth1" +BONDING_SLAVE1="bus-pci-0000:06:08.1" Replace the sample BROADCAST, IPADDR, NETMASK and NETWORK values with the appropriate values for your network. - Note that configuring the bonding device with BOOTPROTO='dhcp' -does not work; the scripts attempt to obtain the device address from -DHCP prior to adding any of the slave devices. Without active slaves, -the DHCP requests are not sent to the network. - The STARTMODE specifies when the device is brought online. The possible values are: @@ -531,9 +624,17 @@ for the bonding mode, link monitoring, and so on here. Do not include the max_bonds bonding parameter; this will confuse the configuration system if you have multiple bonding devices. - Finally, supply one BONDING_SLAVEn="ethX" for each slave, -where "n" is an increasing value, one for each slave, and "ethX" is -the name of the slave device (eth0, eth1, etc). + Finally, supply one BONDING_SLAVEn="slave device" for each +slave. where "n" is an increasing value, one for each slave. The +"slave device" is either an interface name, e.g., "eth0", or a device +specifier for the network device. The interface name is easier to +find, but the ethN names are subject to change at boot time if, e.g., +a device early in the sequence has failed. The device specifiers +(bus-pci-0000:06:08.1 in the example above) specify the physical +network device, and will not change unless the device's bus location +changes (for example, it is moved from one PCI slot to another). The +example above uses one of each type for demonstration purposes; most +configurations will choose one or the other for all slave devices. When all configuration files have been modified or created, networking must be restarted for the configuration changes to take @@ -544,7 +645,7 @@ effect. This can be accomplished via the following: Note that the network control script (/sbin/ifdown) will remove the bonding module as part of the network shutdown processing, so it is not necessary to remove the module by hand if, e.g., the -module paramters have changed. +module parameters have changed. Also, at this writing, YaST/YaST2 will not manage bonding devices (they do not show bonding interfaces on its list of network @@ -559,12 +660,37 @@ format can be found in an example ifcfg template file: Note that the template does not document the various BONDING_ settings described above, but does describe many of the other options. +3.1.1 Using DHCP with sysconfig +------------------------------- + + Under sysconfig, configuring a device with BOOTPROTO='dhcp' +will cause it to query DHCP for its IP address information. At this +writing, this does not function for bonding devices; the scripts +attempt to obtain the device address from DHCP prior to adding any of +the slave devices. Without active slaves, the DHCP requests are not +sent to the network. + +3.1.2 Configuring Multiple Bonds with sysconfig +----------------------------------------------- + + The sysconfig network initialization system is capable of +handling multiple bonding devices. All that is necessary is for each +bonding instance to have an appropriately configured ifcfg-bondX file +(as described above). Do not specify the "max_bonds" parameter to any +instance of bonding, as this will confuse sysconfig. If you require +multiple bonding devices with identical parameters, create multiple +ifcfg-bondX files. + + Because the sysconfig scripts supply the bonding module +options in the ifcfg-bondX file, it is not necessary to add them to +the system /etc/modules.conf or /etc/modprobe.conf configuration file. + 3.2 Configuration with initscripts support ------------------------------------------ This section applies to distros using a version of initscripts with bonding support, for example, Red Hat Linux 9 or Red Hat -Enterprise Linux version 3. On these systems, the network +Enterprise Linux version 3 or 4. On these systems, the network initialization scripts have some knowledge of bonding, and can be configured to control bonding devices. @@ -614,10 +740,11 @@ USERCTL=no Be sure to change the networking specific lines (IPADDR, NETMASK, NETWORK and BROADCAST) to match your network configuration. - Finally, it is necessary to edit /etc/modules.conf to load the -bonding module when the bond0 interface is brought up. The following -sample lines in /etc/modules.conf will load the bonding module, and -select its options: + Finally, it is necessary to edit /etc/modules.conf (or +/etc/modprobe.conf, depending upon your distro) to load the bonding +module with your desired options when the bond0 interface is brought +up. The following lines in /etc/modules.conf (or modprobe.conf) will +load the bonding module, and select its options: alias bond0 bonding options bond0 mode=balance-alb miimon=100 @@ -629,6 +756,33 @@ options for your configuration. will restart the networking subsystem and your bond link should be now up and running. +3.2.1 Using DHCP with initscripts +--------------------------------- + + Recent versions of initscripts (the version supplied with +Fedora Core 3 and Red Hat Enterprise Linux 4 is reported to work) do +have support for assigning IP information to bonding devices via DHCP. + + To configure bonding for DHCP, configure it as described +above, except replace the line "BOOTPROTO=none" with "BOOTPROTO=dhcp" +and add a line consisting of "TYPE=Bonding". Note that the TYPE value +is case sensitive. + +3.2.2 Configuring Multiple Bonds with initscripts +------------------------------------------------- + + At this writing, the initscripts package does not directly +support loading the bonding driver multiple times, so the process for +doing so is the same as described in the "Configuring Multiple Bonds +Manually" section, below. + + NOTE: It has been observed that some Red Hat supplied kernels +are apparently unable to rename modules at load time (the "-obonding1" +part). Attempts to pass that option to modprobe will produce an +"Operation not permitted" error. This has been reported on some +Fedora Core kernels, and has been seen on RHEL 4 as well. On kernels +exhibiting this problem, it will be impossible to configure multiple +bonds with differing parameters. 3.3 Configuring Bonding Manually -------------------------------- @@ -638,10 +792,11 @@ scripts (the sysconfig or initscripts package) do not have specific knowledge of bonding. One such distro is SuSE Linux Enterprise Server version 8. - The general methodology for these systems is to place the -bonding module parameters into /etc/modprobe.conf, then add modprobe -and/or ifenslave commands to the system's global init script. The -name of the global init script differs; for sysconfig, it is + The general method for these systems is to place the bonding +module parameters into /etc/modules.conf or /etc/modprobe.conf (as +appropriate for the installed distro), then add modprobe and/or +ifenslave commands to the system's global init script. The name of +the global init script differs; for sysconfig, it is /etc/init.d/boot.local and for initscripts it is /etc/rc.d/rc.local. For example, if you wanted to make a simple bond of two e100 @@ -649,7 +804,7 @@ devices (presumed to be eth0 and eth1), and have it persist across reboots, edit the appropriate file (/etc/init.d/boot.local or /etc/rc.d/rc.local), and add the following: -modprobe bonding -obond0 mode=balance-alb miimon=100 +modprobe bonding mode=balance-alb miimon=100 modprobe e100 ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up ifenslave bond0 eth0 @@ -657,11 +812,7 @@ ifenslave bond0 eth1 Replace the example bonding module parameters and bond0 network configuration (IP address, netmask, etc) with the appropriate -values for your configuration. The above example loads the bonding -module with the name "bond0," this simplifies the naming if multiple -bonding modules are loaded (each successive instance of the module is -given a different name, and the module instance names match the -bonding interface names). +values for your configuration. Unfortunately, this method will not provide support for the ifup and ifdown scripts on the bond devices. To reload the bonding @@ -684,20 +835,23 @@ appropriate device driver modules. For our example above, you can do the following: # ifconfig bond0 down -# rmmod bond0 +# rmmod bonding # rmmod e100 Again, for convenience, it may be desirable to create a script with these commands. -3.4 Configuring Multiple Bonds ------------------------------- +3.3.1 Configuring Multiple Bonds Manually +----------------------------------------- This section contains information on configuring multiple -bonding devices with differing options. If you require multiple -bonding devices, but all with the same options, see the "max_bonds" -module paramter, documented above. +bonding devices with differing options for those systems whose network +initialization scripts lack support for configuring multiple bonds. + + If you require multiple bonding devices, but all with the same +options, you may wish to use the "max_bonds" module parameter, +documented above. To create multiple bonding devices with differing options, it is necessary to load the bonding driver multiple times. Note that @@ -724,11 +878,16 @@ named "bond0" and creates the bond0 device in balance-rr mode with an miimon of 100. The second instance is named "bond1" and creates the bond1 device in balance-alb mode with an miimon of 50. + In some circumstances (typically with older distributions), +the above does not work, and the second bonding instance never sees +its options. In that case, the second options line can be substituted +as follows: + +install bonding1 /sbin/modprobe bonding -obond1 mode=balance-alb miimon=50 + This may be repeated any number of times, specifying a new and -unique name in place of bond0 or bond1 for each instance. +unique name in place of bond1 for each subsequent instance. - When the appropriate module paramters are in place, then -configure bonding according to the instructions for your distro. 5. Querying Bonding Configuration ================================= @@ -846,8 +1005,8 @@ tagged internally by bonding itself. As a result, bonding must self generated packets. For reasons of simplicity, and to support the use of adapters -that can do VLAN hardware acceleration offloding, the bonding -interface declares itself as fully hardware offloaing capable, it gets +that can do VLAN hardware acceleration offloading, the bonding +interface declares itself as fully hardware offloading capable, it gets the add_vid/kill_vid notifications to gather the necessary information, and it propagates those actions to the slaves. In case of mixed adapter types, hardware accelerated tagged packets that @@ -880,7 +1039,7 @@ bond interface: matches the hardware address of the VLAN interfaces. Note that changing a VLAN interface's HW address would set the -underlying device -- i.e. the bonding interface -- to promiscouos +underlying device -- i.e. the bonding interface -- to promiscuous mode, which might not be what you want. @@ -923,7 +1082,7 @@ down or have a problem making it unresponsive to ARP requests. Having an additional target (or several) increases the reliability of the ARP monitoring. - Multiple ARP targets must be seperated by commas as follows: + Multiple ARP targets must be separated by commas as follows: # example options for ARP monitoring with three targets alias bond0 bonding @@ -1045,7 +1204,7 @@ install bonding /sbin/modprobe tg3; /sbin/modprobe e1000; This will, when loading the bonding module, rather than performing the normal action, instead execute the provided command. This command loads the device drivers in the order needed, then calls -modprobe with --ingore-install to cause the normal action to then take +modprobe with --ignore-install to cause the normal action to then take place. Full documentation on this can be found in the modprobe.conf and modprobe manual pages. @@ -1130,14 +1289,14 @@ association. common to enable promiscuous mode on the device, so that all traffic is seen (instead of seeing only traffic destined for the local host). The bonding driver handles promiscuous mode changes to the bonding -master device (e.g., bond0), and propogates the setting to the slave +master device (e.g., bond0), and propagates the setting to the slave devices. For the balance-rr, balance-xor, broadcast, and 802.3ad modes, -the promiscuous mode setting is propogated to all slaves. +the promiscuous mode setting is propagated to all slaves. For the active-backup, balance-tlb and balance-alb modes, the -promiscuous mode setting is propogated only to the active slave. +promiscuous mode setting is propagated only to the active slave. For balance-tlb mode, the active slave is the slave currently receiving inbound traffic. @@ -1148,46 +1307,182 @@ sending to peers that are unassigned or if the load is unbalanced. For the active-backup, balance-tlb and balance-alb modes, when the active slave changes (e.g., due to a link failure), the -promiscuous setting will be propogated to the new active slave. +promiscuous setting will be propagated to the new active slave. -12. High Availability Information -================================= +12. Configuring Bonding for High Availability +============================================= High Availability refers to configurations that provide maximum network availability by having redundant or backup devices, -links and switches between the host and the rest of the world. - - There are currently two basic methods for configuring to -maximize availability. They are dependent on the network topology and -the primary goal of the configuration, but in general, a configuration -can be optimized for maximum available bandwidth, or for maximum -network availability. +links or switches between the host and the rest of the world. The +goal is to provide the maximum availability of network connectivity +(i.e., the network always works), even though other configurations +could provide higher throughput. 12.1 High Availability in a Single Switch Topology -------------------------------------------------- - If two hosts (or a host and a switch) are directly connected -via multiple physical links, then there is no network availability -penalty for optimizing for maximum bandwidth: there is only one switch -(or peer), so if it fails, you have no alternative access to fail over -to. + If two hosts (or a host and a single switch) are directly +connected via multiple physical links, then there is no availability +penalty to optimizing for maximum bandwidth. In this case, there is +only one switch (or peer), so if it fails, there is no alternative +access to fail over to. Additionally, the bonding load balance modes +support link monitoring of their members, so if individual links fail, +the load will be rebalanced across the remaining devices. + + See Section 13, "Configuring Bonding for Maximum Throughput" +for information on configuring bonding with one peer device. + +12.2 High Availability in a Multiple Switch Topology +---------------------------------------------------- + + With multiple switches, the configuration of bonding and the +network changes dramatically. In multiple switch topologies, there is +a trade off between network availability and usable bandwidth. + + Below is a sample network, configured to maximize the +availability of the network: -Example 1 : host to switch (or other host) + | | + |port3 port3| + +-----+----+ +-----+----+ + | |port2 ISL port2| | + | switch A +--------------------------+ switch B | + | | | | + +-----+----+ +-----++---+ + |port1 port1| + | +-------+ | + +-------------+ host1 +---------------+ + eth0 +-------+ eth1 - +----------+ +----------+ - | |eth0 eth0| switch | - | Host A +--------------------------+ or | - | +--------------------------+ other | - | |eth1 eth1| host | - +----------+ +----------+ + In this configuration, there is a link between the two +switches (ISL, or inter switch link), and multiple ports connecting to +the outside world ("port3" on each switch). There is no technical +reason that this could not be extended to a third switch. +12.2.1 HA Bonding Mode Selection for Multiple Switch Topology +------------------------------------------------------------- -12.1.1 Bonding Mode Selection for single switch topology --------------------------------------------------------- + In a topology such as the example above, the active-backup and +broadcast modes are the only useful bonding modes when optimizing for +availability; the other modes require all links to terminate on the +same peer for them to behave rationally. + +active-backup: This is generally the preferred mode, particularly if + the switches have an ISL and play together well. If the + network configuration is such that one switch is specifically + a backup switch (e.g., has lower capacity, higher cost, etc), + then the primary option can be used to insure that the + preferred link is always used when it is available. + +broadcast: This mode is really a special purpose mode, and is suitable + only for very specific needs. For example, if the two + switches are not connected (no ISL), and the networks beyond + them are totally independent. In this case, if it is + necessary for some specific one-way traffic to reach both + independent networks, then the broadcast mode may be suitable. + +12.2.2 HA Link Monitoring Selection for Multiple Switch Topology +---------------------------------------------------------------- + + The choice of link monitoring ultimately depends upon your +switch. If the switch can reliably fail ports in response to other +failures, then either the MII or ARP monitors should work. For +example, in the above example, if the "port3" link fails at the remote +end, the MII monitor has no direct means to detect this. The ARP +monitor could be configured with a target at the remote end of port3, +thus detecting that failure without switch support. + + In general, however, in a multiple switch topology, the ARP +monitor can provide a higher level of reliability in detecting end to +end connectivity failures (which may be caused by the failure of any +individual component to pass traffic for any reason). Additionally, +the ARP monitor should be configured with multiple targets (at least +one for each switch in the network). This will insure that, +regardless of which switch is active, the ARP monitor has a suitable +target to query. + + +13. Configuring Bonding for Maximum Throughput +============================================== + +13.1 Maximizing Throughput in a Single Switch Topology +------------------------------------------------------ + + In a single switch configuration, the best method to maximize +throughput depends upon the application and network environment. The +various load balancing modes each have strengths and weaknesses in +different environments, as detailed below. + + For this discussion, we will break down the topologies into +two categories. Depending upon the destination of most traffic, we +categorize them into either "gatewayed" or "local" configurations. + + In a gatewayed configuration, the "switch" is acting primarily +as a router, and the majority of traffic passes through this router to +other networks. An example would be the following: + + + +----------+ +----------+ + | |eth0 port1| | to other networks + | Host A +---------------------+ router +-------------------> + | +---------------------+ | Hosts B and C are out + | |eth1 port2| | here somewhere + +----------+ +----------+ + + The router may be a dedicated router device, or another host +acting as a gateway. For our discussion, the important point is that +the majority of traffic from Host A will pass through the router to +some other network before reaching its final destination. + + In a gatewayed network configuration, although Host A may +communicate with many other systems, all of its traffic will be sent +and received via one other peer on the local network, the router. + + Note that the case of two systems connected directly via +multiple physical links is, for purposes of configuring bonding, the +same as a gatewayed configuration. In that case, it happens that all +traffic is destined for the "gateway" itself, not some other network +beyond the gateway. + + In a local configuration, the "switch" is acting primarily as +a switch, and the majority of traffic passes through this switch to +reach other stations on the same network. An example would be the +following: + + +----------+ +----------+ +--------+ + | |eth0 port1| +-------+ Host B | + | Host A +------------+ switch |port3 +--------+ + | +------------+ | +--------+ + | |eth1 port2| +------------------+ Host C | + +----------+ +----------+port4 +--------+ + + + Again, the switch may be a dedicated switch device, or another +host acting as a gateway. For our discussion, the important point is +that the majority of traffic from Host A is destined for other hosts +on the same local network (Hosts B and C in the above example). + + In summary, in a gatewayed configuration, traffic to and from +the bonded device will be to the same MAC level peer on the network +(the gateway itself, i.e., the router), regardless of its final +destination. In a local configuration, traffic flows directly to and +from the final destinations, thus, each destination (Host B, Host C) +will be addressed directly by their individual MAC addresses. + + This distinction between a gatewayed and a local network +configuration is important because many of the load balancing modes +available use the MAC addresses of the local network source and +destination to make load balancing decisions. The behavior of each +mode is described below. + + +13.1.1 MT Bonding Mode Selection for Single Switch Topology +----------------------------------------------------------- This configuration is the easiest to set up and to understand, although you will have to decide which bonding mode best suits your -needs. The tradeoffs for each mode are detailed below: +needs. The trade offs for each mode are detailed below: balance-rr: This mode is the only mode that will permit a single TCP/IP connection to stripe traffic across multiple @@ -1206,6 +1501,23 @@ balance-rr: This mode is the only mode that will permit a single interface's worth of throughput, even after adjusting tcp_reordering. + Note that this out of order delivery occurs when both the + sending and receiving systems are utilizing a multiple + interface bond. Consider a configuration in which a + balance-rr bond feeds into a single higher capacity network + channel (e.g., multiple 100Mb/sec ethernets feeding a single + gigabit ethernet via an etherchannel capable switch). In this + configuration, traffic sent from the multiple 100Mb devices to + a destination connected to the gigabit device will not see + packets out of order. However, traffic sent from the gigabit + device to the multiple 100Mb devices may or may not see + traffic out of order, depending upon the balance policy of the + switch. Many switches do not support any modes that stripe + traffic (instead choosing a port based upon IP or MAC level + addresses); for those devices, traffic flowing from the + gigabit device to the many 100Mb devices will only utilize one + interface. + If you are utilizing protocols other than TCP/IP, UDP for example, and your application can tolerate out of order delivery, then this mode can allow for single stream datagram @@ -1220,16 +1532,21 @@ active-backup: There is not much advantage in this network topology to connected to the same peer as the primary. In this case, a load balancing mode (with link monitoring) will provide the same level of network availability, but with increased - available bandwidth. On the plus side, it does not require - any configuration of the switch. + available bandwidth. On the plus side, active-backup mode + does not require any configuration of the switch, so it may + have value if the hardware available does not support any of + the load balance modes. balance-xor: This mode will limit traffic such that packets destined for specific peers will always be sent over the same interface. Since the destination is determined by the MAC - addresses involved, this may be desirable if you have a large - network with many hosts. It is likely to be suboptimal if all - your traffic is passed through a single router, however. As - with balance-rr, the switch ports need to be configured for + addresses involved, this mode works best in a "local" network + configuration (as described above), with destinations all on + the same local network. This mode is likely to be suboptimal + if all your traffic is passed through a single router (i.e., a + "gatewayed" network configuration, as described above). + + As with balance-rr, the switch ports need to be configured for "etherchannel" or "trunking." broadcast: Like active-backup, there is not much advantage to this @@ -1241,122 +1558,131 @@ broadcast: Like active-backup, there is not much advantage to this protocol includes automatic configuration of the aggregates, so minimal manual configuration of the switch is needed (typically only to designate that some set of devices is - usable for 802.3ad). The 802.3ad standard also mandates that - frames be delivered in order (within certain limits), so in - general single connections will not see misordering of + available for 802.3ad). The 802.3ad standard also mandates + that frames be delivered in order (within certain limits), so + in general single connections will not see misordering of packets. The 802.3ad mode does have some drawbacks: the standard mandates that all devices in the aggregate operate at the same speed and duplex. Also, as with all bonding load balance modes other than balance-rr, no single connection will be able to utilize more than a single interface's worth of - bandwidth. Additionally, the linux bonding 802.3ad - implementation distributes traffic by peer (using an XOR of - MAC addresses), so in general all traffic to a particular - destination will use the same interface. Finally, the 802.3ad - mode mandates the use of the MII monitor, therefore, the ARP - monitor is not available in this mode. - -balance-tlb: This mode is also a good choice for this type of - topology. It has no special switch configuration - requirements, and balances outgoing traffic by peer, in a - vaguely intelligent manner (not a simple XOR as in balance-xor - or 802.3ad mode), so that unlucky MAC addresses will not all - "bunch up" on a single interface. Interfaces may be of - differing speeds. On the down side, in this mode all incoming - traffic arrives over a single interface, this mode requires - certain ethtool support in the network device driver of the - slave interfaces, and the ARP monitor is not available. - -balance-alb: This mode is everything that balance-tlb is, and more. It - has all of the features (and restrictions) of balance-tlb, and - will also balance incoming traffic from peers (as described in - the Bonding Module Options section, above). The only extra - down side to this mode is that the network device driver must - support changing the hardware address while the device is - open. - -12.1.2 Link Monitoring for Single Switch Topology -------------------------------------------------- + bandwidth. + + Additionally, the linux bonding 802.3ad implementation + distributes traffic by peer (using an XOR of MAC addresses), + so in a "gatewayed" configuration, all outgoing traffic will + generally use the same device. Incoming traffic may also end + up on a single device, but that is dependent upon the + balancing policy of the peer's 8023.ad implementation. In a + "local" configuration, traffic will be distributed across the + devices in the bond. + + Finally, the 802.3ad mode mandates the use of the MII monitor, + therefore, the ARP monitor is not available in this mode. + +balance-tlb: The balance-tlb mode balances outgoing traffic by peer. + Since the balancing is done according to MAC address, in a + "gatewayed" configuration (as described above), this mode will + send all traffic across a single device. However, in a + "local" network configuration, this mode balances multiple + local network peers across devices in a vaguely intelligent + manner (not a simple XOR as in balance-xor or 802.3ad mode), + so that mathematically unlucky MAC addresses (i.e., ones that + XOR to the same value) will not all "bunch up" on a single + interface. + + Unlike 802.3ad, interfaces may be of differing speeds, and no + special switch configuration is required. On the down side, + in this mode all incoming traffic arrives over a single + interface, this mode requires certain ethtool support in the + network device driver of the slave interfaces, and the ARP + monitor is not available. + +balance-alb: This mode is everything that balance-tlb is, and more. + It has all of the features (and restrictions) of balance-tlb, + and will also balance incoming traffic from local network + peers (as described in the Bonding Module Options section, + above). + + The only additional down side to this mode is that the network + device driver must support changing the hardware address while + the device is open. + +13.1.2 MT Link Monitoring for Single Switch Topology +---------------------------------------------------- The choice of link monitoring may largely depend upon which mode you choose to use. The more advanced load balancing modes do not support the use of the ARP monitor, and are thus restricted to using -the MII monitor (which does not provide as high a level of assurance -as the ARP monitor). - - -12.2 High Availability in a Multiple Switch Topology ----------------------------------------------------- - - With multiple switches, the configuration of bonding and the -network changes dramatically. In multiple switch topologies, there is -a tradeoff between network availability and usable bandwidth. - - Below is a sample network, configured to maximize the -availability of the network: - - | | - |port3 port3| - +-----+----+ +-----+----+ - | |port2 ISL port2| | - | switch A +--------------------------+ switch B | - | | | | - +-----+----+ +-----++---+ - |port1 port1| - | +-------+ | - +-------------+ host1 +---------------+ - eth0 +-------+ eth1 - - In this configuration, there is a link between the two -switches (ISL, or inter switch link), and multiple ports connecting to -the outside world ("port3" on each switch). There is no technical -reason that this could not be extended to a third switch. - -12.2.1 Bonding Mode Selection for Multiple Switch Topology ----------------------------------------------------------- - - In a topology such as this, the active-backup and broadcast -modes are the only useful bonding modes; the other modes require all -links to terminate on the same peer for them to behave rationally. - -active-backup: This is generally the preferred mode, particularly if - the switches have an ISL and play together well. If the - network configuration is such that one switch is specifically - a backup switch (e.g., has lower capacity, higher cost, etc), - then the primary option can be used to insure that the - preferred link is always used when it is available. - -broadcast: This mode is really a special purpose mode, and is suitable - only for very specific needs. For example, if the two - switches are not connected (no ISL), and the networks beyond - them are totally independant. In this case, if it is - necessary for some specific one-way traffic to reach both - independent networks, then the broadcast mode may be suitable. - -12.2.2 Link Monitoring Selection for Multiple Switch Topology +the MII monitor (which does not provide as high a level of end to end +assurance as the ARP monitor). + +13.2 Maximum Throughput in a Multiple Switch Topology +----------------------------------------------------- + + Multiple switches may be utilized to optimize for throughput +when they are configured in parallel as part of an isolated network +between two or more systems, for example: + + +-----------+ + | Host A | + +-+---+---+-+ + | | | + +--------+ | +---------+ + | | | + +------+---+ +-----+----+ +-----+----+ + | Switch A | | Switch B | | Switch C | + +------+---+ +-----+----+ +-----+----+ + | | | + +--------+ | +---------+ + | | | + +-+---+---+-+ + | Host B | + +-----------+ + + In this configuration, the switches are isolated from one +another. One reason to employ a topology such as this is for an +isolated network with many hosts (a cluster configured for high +performance, for example), using multiple smaller switches can be more +cost effective than a single larger switch, e.g., on a network with 24 +hosts, three 24 port switches can be significantly less expensive than +a single 72 port switch. + + If access beyond the network is required, an individual host +can be equipped with an additional network device connected to an +external network; this host then additionally acts as a gateway. + +13.2.1 MT Bonding Mode Selection for Multiple Switch Topology ------------------------------------------------------------- - The choice of link monitoring ultimately depends upon your -switch. If the switch can reliably fail ports in response to other -failures, then either the MII or ARP monitors should work. For -example, in the above example, if the "port3" link fails at the remote -end, the MII monitor has no direct means to detect this. The ARP -monitor could be configured with a target at the remote end of port3, -thus detecting that failure without switch support. + In actual practice, the bonding mode typically employed in +configurations of this type is balance-rr. Historically, in this +network configuration, the usual caveats about out of order packet +delivery are mitigated by the use of network adapters that do not do +any kind of packet coalescing (via the use of NAPI, or because the +device itself does not generate interrupts until some number of +packets has arrived). When employed in this fashion, the balance-rr +mode allows individual connections between two hosts to effectively +utilize greater than one interface's bandwidth. - In general, however, in a multiple switch topology, the ARP -monitor can provide a higher level of reliability in detecting link -failures. Additionally, it should be configured with multiple targets -(at least one for each switch in the network). This will insure that, -regardless of which switch is active, the ARP monitor has a suitable -target to query. +13.2.2 MT Link Monitoring for Multiple Switch Topology +------------------------------------------------------ + Again, in actual practice, the MII monitor is most often used +in this configuration, as performance is given preference over +availability. The ARP monitor will function in this topology, but its +advantages over the MII monitor are mitigated by the volume of probes +needed as the number of systems involved grows (remember that each +host in the network is configured with bonding). -12.3 Switch Behavior Issues for High Availability -------------------------------------------------- +14. Switch Behavior Issues +========================== - You may encounter issues with the timing of link up and down -reporting by the switch. +14.1 Link Establishment and Failover Delays +------------------------------------------- + + Some switches exhibit undesirable behavior with regard to the +timing of link up and down reporting by the switch. First, when a link comes up, some switches may indicate that the link is up (carrier available), but not pass traffic over the @@ -1370,30 +1696,70 @@ relevant interface(s). Second, some switches may "bounce" the link state one or more times while a link is changing state. This occurs most commonly while the switch is initializing. Again, an appropriate updelay value may -help, but note that if all links are down, then updelay is ignored -when any link becomes active (the slave closest to completing its -updelay is chosen). +help. Note that when a bonding interface has no active links, the -driver will immediately reuse the first link that goes up, even if -updelay parameter was specified. If there are slave interfaces -waiting for the updelay timeout to expire, the interface that first -went into that state will be immediately reused. This reduces down -time of the network if the value of updelay has been overestimated. +driver will immediately reuse the first link that goes up, even if the +updelay parameter has been specified (the updelay is ignored in this +case). If there are slave interfaces waiting for the updelay timeout +to expire, the interface that first went into that state will be +immediately reused. This reduces down time of the network if the +value of updelay has been overestimated, and since this occurs only in +cases with no connectivity, there is no additional penalty for +ignoring the updelay. In addition to the concerns about switch timings, if your switches take a long time to go into backup mode, it may be desirable to not activate a backup interface immediately after a link goes down. Failover may be delayed via the downdelay bonding module option. -13. Hardware Specific Considerations +14.2 Duplicated Incoming Packets +-------------------------------- + + It is not uncommon to observe a short burst of duplicated +traffic when the bonding device is first used, or after it has been +idle for some period of time. This is most easily observed by issuing +a "ping" to some other host on the network, and noticing that the +output from ping flags duplicates (typically one per slave). + + For example, on a bond in active-backup mode with five slaves +all connected to one switch, the output may appear as follows: + +# ping -n 10.0.4.2 +PING 10.0.4.2 (10.0.4.2) from 10.0.3.10 : 56(84) bytes of data. +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.7 ms +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!) +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!) +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!) +64 bytes from 10.0.4.2: icmp_seq=1 ttl=64 time=13.8 ms (DUP!) +64 bytes from 10.0.4.2: icmp_seq=2 ttl=64 time=0.216 ms +64 bytes from 10.0.4.2: icmp_seq=3 ttl=64 time=0.267 ms +64 bytes from 10.0.4.2: icmp_seq=4 ttl=64 time=0.222 ms + + This is not due to an error in the bonding driver, rather, it +is a side effect of how many switches update their MAC forwarding +tables. Initially, the switch does not associate the MAC address in +the packet with a particular switch port, and so it may send the +traffic to all ports until its MAC forwarding table is updated. Since +the interfaces attached to the bond may occupy multiple ports on a +single switch, when the switch (temporarily) floods the traffic to all +ports, the bond device receives multiple copies of the same packet +(one per slave device). + + The duplicated packet behavior is switch dependent, some +switches exhibit this, and some do not. On switches that display this +behavior, it can be induced by clearing the MAC forwarding table (on +most Cisco switches, the privileged command "clear mac address-table +dynamic" will accomplish this). + +15. Hardware Specific Considerations ==================================== This section contains additional information for configuring bonding on specific hardware platforms, or for interfacing bonding with particular switches or other devices. -13.1 IBM BladeCenter +15.1 IBM BladeCenter -------------------- This applies to the JS20 and similar systems. @@ -1407,12 +1773,12 @@ JS20 network adapter information -------------------------------- All JS20s come with two Broadcom Gigabit Ethernet ports -integrated on the planar. In the BladeCenter chassis, the eth0 port -of all JS20 blades is hard wired to I/O Module #1; similarly, all eth1 -ports are wired to I/O Module #2. An add-on Broadcom daughter card -can be installed on a JS20 to provide two more Gigabit Ethernet ports. -These ports, eth2 and eth3, are wired to I/O Modules 3 and 4, -respectively. +integrated on the planar (that's "motherboard" in IBM-speak). In the +BladeCenter chassis, the eth0 port of all JS20 blades is hard wired to +I/O Module #1; similarly, all eth1 ports are wired to I/O Module #2. +An add-on Broadcom daughter card can be installed on a JS20 to provide +two more Gigabit Ethernet ports. These ports, eth2 and eth3, are +wired to I/O Modules 3 and 4, respectively. Each I/O Module may contain either a switch or a passthrough module (which allows ports to be directly connected to an external @@ -1432,29 +1798,30 @@ BladeCenter networking configuration of ways, this discussion will be confined to describing basic configurations. - Normally, Ethernet Switch Modules (ESM) are used in I/O + Normally, Ethernet Switch Modules (ESMs) are used in I/O modules 1 and 2. In this configuration, the eth0 and eth1 ports of a JS20 will be connected to different internal switches (in the respective I/O modules). - An optical passthru module (OPM) connects the I/O module -directly to an external switch. By using OPMs in I/O module #1 and -#2, the eth0 and eth1 interfaces of a JS20 can be redirected to the -outside world and connected to a common external switch. - - Depending upon the mix of ESM and OPM modules, the network -will appear to bonding as either a single switch topology (all OPM -modules) or as a multiple switch topology (one or more ESM modules, -zero or more OPM modules). It is also possible to connect ESM modules -together, resulting in a configuration much like the example in "High -Availability in a multiple switch topology." - -Requirements for specifc modes ------------------------------- - - The balance-rr mode requires the use of OPM modules for -devices in the bond, all connected to an common external switch. That -switch must be configured for "etherchannel" or "trunking" on the + A passthrough module (OPM or CPM, optical or copper, +passthrough module) connects the I/O module directly to an external +switch. By using PMs in I/O module #1 and #2, the eth0 and eth1 +interfaces of a JS20 can be redirected to the outside world and +connected to a common external switch. + + Depending upon the mix of ESMs and PMs, the network will +appear to bonding as either a single switch topology (all PMs) or as a +multiple switch topology (one or more ESMs, zero or more PMs). It is +also possible to connect ESMs together, resulting in a configuration +much like the example in "High Availability in a Multiple Switch +Topology," above. + +Requirements for specific modes +------------------------------- + + The balance-rr mode requires the use of passthrough modules +for devices in the bond, all connected to an common external switch. +That switch must be configured for "etherchannel" or "trunking" on the appropriate ports, as is usual for balance-rr. The balance-alb and balance-tlb modes will function with @@ -1484,17 +1851,18 @@ connected to the JS20 system. Other concerns -------------- - The Serial Over LAN link is established over the primary + The Serial Over LAN (SoL) link is established over the primary ethernet (eth0) only, therefore, any loss of link to eth0 will result in losing your SoL connection. It will not fail over with other -network traffic. +network traffic, as the SoL system is beyond the control of the +bonding driver. It may be desirable to disable spanning tree on the switch (either the internal Ethernet Switch Module, or an external switch) to -avoid fail-over delays issues when using bonding. +avoid fail-over delay issues when using bonding. -14. Frequently Asked Questions +16. Frequently Asked Questions ============================== 1. Is it SMP safe? @@ -1505,8 +1873,8 @@ The new driver was designed to be SMP safe from the start. 2. What type of cards will work with it? Any Ethernet type cards (you can even mix cards - a Intel -EtherExpress PRO/100 and a 3com 3c905b, for example). They need not -be of the same speed. +EtherExpress PRO/100 and a 3com 3c905b, for example). For most modes, +devices need not be of the same speed. 3. How many bonding devices can I have? @@ -1524,11 +1892,12 @@ system. disabled. The active-backup mode will fail over to a backup link, and other modes will ignore the failed link. The link will continue to be monitored, and should it recover, it will rejoin the bond (in whatever -manner is appropriate for the mode). See the section on High -Availability for additional information. +manner is appropriate for the mode). See the sections on High +Availability and the documentation for each mode for additional +information. Link monitoring can be enabled via either the miimon or -arp_interval paramters (described in the module paramters section, +arp_interval parameters (described in the module parameters section, above). In general, miimon monitors the carrier state as sensed by the underlying network device, and the arp monitor (arp_interval) monitors connectivity to another host on the local network. @@ -1536,7 +1905,7 @@ monitors connectivity to another host on the local network. If no link monitoring is configured, the bonding driver will be unable to detect link failures, and will assume that all links are always available. This will likely result in lost packets, and a -resulting degredation of performance. The precise performance loss +resulting degradation of performance. The precise performance loss depends upon the bonding mode and network configuration. 6. Can bonding be used for High Availability? @@ -1550,12 +1919,12 @@ depends upon the bonding mode and network configuration. In the basic balance modes (balance-rr and balance-xor), it works with any system that supports etherchannel (also called trunking). Most managed switches currently available have such -support, and many unmananged switches as well. +support, and many unmanaged switches as well. The advanced balance modes (balance-tlb and balance-alb) do not have special switch requirements, but do need device drivers that support specific features (described in the appropriate section under -module paramters, above). +module parameters, above). In 802.3ad mode, it works with with systems that support IEEE 802.3ad Dynamic Link Aggregation. Most managed and many unmanaged @@ -1565,17 +1934,19 @@ switches currently available support 802.3ad. 8. Where does a bonding device get its MAC address from? - If not explicitly configured with ifconfig, the MAC address of -the bonding device is taken from its first slave device. This MAC -address is then passed to all following slaves and remains persistent -(even if the the first slave is removed) until the bonding device is -brought down or reconfigured. + If not explicitly configured (with ifconfig or ip link), the +MAC address of the bonding device is taken from its first slave +device. This MAC address is then passed to all following slaves and +remains persistent (even if the the first slave is removed) until the +bonding device is brought down or reconfigured. If you wish to change the MAC address, you can set it with -ifconfig: +ifconfig or ip link: # ifconfig bond0 hw ether 00:11:22:33:44:55 +# ip link set bond0 address 66:77:88:99:aa:bb + The MAC address can be also changed by bringing down/up the device and then changing its slaves (or their order): @@ -1591,23 +1962,28 @@ from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then restore the MAC addresses that the slaves had before they were enslaved. -15. Resources and Links +16. Resources and Links ======================= The latest version of the bonding driver can be found in the latest version of the linux kernel, found on http://kernel.org +The latest version of this document can be found in either the latest +kernel source (named Documentation/networking/bonding.txt), or on the +bonding sourceforge site: + +http://www.sourceforge.net/projects/bonding + Discussions regarding the bonding driver take place primarily on the bonding-devel mailing list, hosted at sourceforge.net. If you have -questions or problems, post them to the list. +questions or problems, post them to the list. The list address is: bonding-devel@lists.sourceforge.net -https://lists.sourceforge.net/lists/listinfo/bonding-devel - -There is also a project site on sourceforge. + The administrative interface (to subscribe or unsubscribe) can +be found at: -http://www.sourceforge.net/projects/bonding +https://lists.sourceforge.net/lists/listinfo/bonding-devel Donald Becker's Ethernet Drivers and diag programs may be found at : - http://www.scyld.com/network/ -- cgit v1.2.3 From 3f309db33e7868fe11f8fc3a0dd291703df3c662 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 27 Jun 2005 15:47:25 -0700 Subject: [PATCH] sk98lin: fix workaround for yukon-lite chipset (> rev 7) Yukon-Lite chipset needs workaround for revision 7 (or later). Without this patch, chip gets stuck in low power mode and never boots. Newer SysKonnect vendor code already had same patch. Related bug in skge is http://bugs.gentoo.org/87822 Chris, please add for 2.6.12.2 Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sk98lin/skgeinit.c | 2 +- drivers/net/sk98lin/skxmac2.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c index df4483429a77..6cb49dd02251 100644 --- a/drivers/net/sk98lin/skgeinit.c +++ b/drivers/net/sk98lin/skgeinit.c @@ -2016,7 +2016,7 @@ SK_IOC IoC) /* IO context */ * we set the PHY to coma mode and switch to D3 power state. */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* for all ports switch PHY to coma mode */ for (i = 0; i < pAC->GIni.GIMacsFound; i++) { diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c index 94a09deecb32..42d2d963150a 100644 --- a/drivers/net/sk98lin/skxmac2.c +++ b/drivers/net/sk98lin/skxmac2.c @@ -1065,7 +1065,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* WA code for COMA mode */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { SK_IN32(IoC, B2_GP_IO, &DWord); @@ -1110,7 +1110,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* WA code for COMA mode */ if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { SK_IN32(IoC, B2_GP_IO, &DWord); @@ -2126,7 +2126,7 @@ SK_U8 Mode) /* low power mode */ int Ret = 0; if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* save current power mode */ LastMode = pAC->GIni.GP[Port].PPhyPowerState; @@ -2253,7 +2253,7 @@ int Port) /* Port Index (e.g. MAC_1) */ int Ret = 0; if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) { + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { /* save current power mode */ LastMode = pAC->GIni.GP[Port].PPhyPowerState; -- cgit v1.2.3 From af44f5bf775e0d36aa5879c94369216ff6f717a6 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 30 Jun 2005 06:40:18 -0700 Subject: [PATCH] Fix OMAP specific typo in smc91x.h --ReaqsoxgOBHFXBhH Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi Jeff, Here's a little patch fixing a typo in smc91x.h. Regards, Tony --ReaqsoxgOBHFXBhH Content-Type: text/x-chdr; charset=us-ascii Content-Disposition: inline; filename="patch-fix-typo-smc91x.h" Signed-off-by: Jeff Garzik --- drivers/net/smc91x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 7089d86e857a..a9b06b8d8e3f 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -188,7 +188,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_IRQ_TRIGGER_TYPE (( \ machine_is_omap_h2() \ || machine_is_omap_h3() \ - || (machine_is_omap_innovator() && !cpu_is_omap150()) \ + || (machine_is_omap_innovator() && !cpu_is_omap1510()) \ ) ? IRQT_FALLING : IRQT_RISING) -- cgit v1.2.3 From e064cd7e3ac797df1e81b55ff4fed5fca5d106b5 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 4 Jul 2005 18:30:42 +0100 Subject: [PATCH] SMP fix for 6pack driver Drivers really only work well in SMP if they actually can be selected. This is a leftover from the time when the 6pack drive only used to be a bitrotten variant of the slip driver. Signed-off-by: Ralf Baechle DL5RB Kconfig | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Signed-off-by: Jeff Garzik --- drivers/net/hamradio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig index 7cdebe1a0b61..0cd54306e636 100644 --- a/drivers/net/hamradio/Kconfig +++ b/drivers/net/hamradio/Kconfig @@ -17,7 +17,7 @@ config MKISS config 6PACK tristate "Serial port 6PACK driver" - depends on AX25 && BROKEN_ON_SMP + depends on AX25 ---help--- 6pack is a transmission protocol for the data exchange between your PC and your TNC (the Terminal Node Controller acts as a kind of -- cgit v1.2.3 From 02459eaab98a6a57717bc0cacede148fc76af881 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Sat, 30 Jul 2005 23:49:54 +0100 Subject: [PATCH] Display name of fbdev device This patch displays the name of the fbdev driver in sysfs. Down the road this will replace the current proc handle we have. Signed-off-by: James Simmons Signed-off-by: Linus Torvalds --- drivers/video/fbsysfs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index ed1d4d1ac4f7..1147b899f007 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -414,6 +414,13 @@ static ssize_t show_pan(struct class_device *class_device, char *buf) fb_info->var.xoffset); } +static ssize_t show_name(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device); + + return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id); +} + static struct class_device_attribute class_device_attrs[] = { __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), @@ -424,6 +431,7 @@ static struct class_device_attribute class_device_attrs[] = { __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes), __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan), __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), + __ATTR(name, S_IRUGO, show_name, NULL), }; int fb_init_class_device(struct fb_info *fb_info) -- cgit v1.2.3 From 7544953685859875b5ac0260b6b1856066c092d6 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Mon, 1 Aug 2005 11:00:45 -0400 Subject: [PATCH] inotify: fix file deletion by rename detection When a file is moved over an existing file that you are watching, inotify won't send you a DELETE_SELF event and it won't unref the inode until the inotify instance is closed by the application. Signed-off-by: John McCutchan Signed-off-by: Robert Love Signed-off-by: Linus Torvalds --- fs/namei.c | 2 +- include/linux/fsnotify.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 02a824cd3c5c..4a27eb798118 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2218,7 +2218,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); if (!error) { const char *new_name = old_dentry->d_name.name; - fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir); + fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, new_dentry->d_inode); } fsnotify_oldname_free(old_name); diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index d07a92c94776..e96a4306ab3b 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -21,7 +21,7 @@ */ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, const char *old_name, const char *new_name, - int isdir) + int isdir, struct inode *target) { u32 cookie = inotify_get_cookie(); @@ -36,6 +36,11 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, isdir = IN_ISDIR; inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name); inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name); + + if (target) { + inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL); + inotify_inode_is_dead(target); + } } /* -- cgit v1.2.3 From b9c55d29e9fced1eb1b4c252b2efd4b55a0c3c7f Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Mon, 1 Aug 2005 11:00:45 -0400 Subject: [PATCH] inotify: fix race between the kernel and user space When you rm a watch, an IN_IGNORED event is sent down the event queue with the watch descriptor that you just rm'd. If you then add a watch you could get the ignored watch's wd and if you haven't read the entire event queue, user space will think that it's newly created watch was just ignored. To avoid this problem we just use idr_get_new_above instead of idr_get_new. Signed-off-by: John McCutchan Signed-off-by: Robert Love Signed-off-by: Linus Torvalds --- fs/inotify.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/inotify.c b/fs/inotify.c index a8a714e48140..27ebcac5e07f 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -90,6 +90,7 @@ struct inotify_device { unsigned int queue_size; /* size of the queue (bytes) */ unsigned int event_count; /* number of pending events */ unsigned int max_events; /* maximum number of events */ + u32 last_wd; /* the last wd allocated */ }; /* @@ -352,7 +353,7 @@ static int inotify_dev_get_wd(struct inotify_device *dev, do { if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL))) return -ENOSPC; - ret = idr_get_new(&dev->idr, watch, &watch->wd); + ret = idr_get_new_above(&dev->idr, watch, dev->last_wd, &watch->wd); } while (ret == -EAGAIN); return ret; @@ -401,6 +402,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev, return ERR_PTR(ret); } + dev->last_wd = ret; watch->mask = mask; atomic_set(&watch->count, 0); INIT_LIST_HEAD(&watch->d_list); @@ -899,6 +901,7 @@ asmlinkage long sys_inotify_init(void) dev->queue_size = 0; dev->max_events = inotify_max_queued_events; dev->user = user; + dev->last_wd = 0; atomic_set(&dev->count, 0); get_inotify_dev(dev); -- cgit v1.2.3 From 2b8d4669376332a6819e21994a78ecd5502d3ebc Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 1 Aug 2005 14:16:55 +0200 Subject: [PATCH] pcmcia: defer ide-cs initialization after other IDE drivers started up Avoid registering PCMCIA CF cards before other IDE stuff. This means the risk of /dev/hd* being re-ordered is lessened. The _sane_ thing to assert any ordering is to use udev, nameif and so on, of course. Signed-off-by: Dominik Brodowski Signed-off-by: Linus Torvalds --- drivers/ide/legacy/ide-cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 03747439ac9c..f1d1ec4e9677 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -508,5 +508,5 @@ static void __exit exit_ide_cs(void) BUG_ON(dev_list != NULL); } -module_init(init_ide_cs); +late_initcall(init_ide_cs); module_exit(exit_ide_cs); -- cgit v1.2.3 From 5d546f54324e04747e82ccbb4ea85f54bdcacd6d Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 1 Aug 2005 14:55:51 +0200 Subject: [PATCH] pcmcia: fix multiple insertion of multifunction cards The ordering of setting and clearing device_add_pending went wrong on some occasions, causing multifunction cards only to be handled correctly on the first insertion, not on subsequent ones. Signed-off-by: Dominik Brodowski Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index d63f22a5bf7e..43da2e92d50f 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -589,8 +589,8 @@ static void pcmcia_delayed_add_pseudo_device(void *data) static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) { if (!s->pcmcia_state.device_add_pending) { - schedule_work(&s->device_add); s->pcmcia_state.device_add_pending = 1; + schedule_work(&s->device_add); } return; } -- cgit v1.2.3 From 6cb54819d7b1867053e2dfd8c0ca3a8dc65a7eff Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 1 Aug 2005 13:39:13 +0200 Subject: [PATCH] remove sys_set_zone_reclaim() This removes sys_set_zone_reclaim() for now. While i'm sure Martin is trying to solve a real problem, we must not hard-code an incomplete and insufficient approach into a syscall, because syscalls are pretty much for eternity. I am quite strongly convinced that this syscall must not hit v2.6.13 in its current form. Firstly, the syscall lacks basic syscall design: e.g. it allows the global setting of VM policy for unprivileged users. (!) [ Imagine an Oracle installation and a SAP installation on the same NUMA box fighting over the 'optimal' setting for this flag. What will they do? Will they try to set the flag to their own preferred value every second or so? ] Secondly, it was added based on a single datapoint from Martin: http://marc.theaimsgroup.com/?l=linux-mm&m=111763597218177&w=2 where Martin characterizes the numbers the following way: ' Run-to-run variability for "make -j" is huge, so these numbers aren't terribly useful except to see that with reclaim the benchmark still finishes in a reasonable amount of time. ' in other words: the fundamental problem has likely not been solved, only a tendential move into the right direction has been observed, and a handful of numbers were picked out of a set of hugely variable results, without showing the variability data. How much variance is there run-to-run? I'd really suggest to first walk the walk and see what's needed to get stable & predictable kernel compilation numbers on that NUMA box, before adding random syscalls to tune a particular aspect of the VM ... which approach might not even matter once the whole picture has been analyzed and understood! The third, most important point is that the syscall exposes VM tuning internals in a completely unstructured way. What sense does it make to have a _GLOBAL_ per-node setting for 'should we go to another node for reclaim'? If then it might make sense to do this per-app, via numalib or so. The change is minimalistic in that it doesnt remove the syscall and the underlying infrastructure changes, only the user-visible changes. We could perhaps add a CAP_SYS_ADMIN-only sysctl for this hack, a'ka /proc/sys/vm/swappiness, but even that looks quite counterproductive when the generic approach is that we are trying to reduce the number of external factors in the VM balance picture. Signed-off-by: Ingo Molnar Signed-off-by: Linus Torvalds --- arch/i386/kernel/syscall_table.S | 2 +- arch/ia64/kernel/entry.S | 2 +- kernel/sys_ni.c | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 468500a7e894..9b21a31d4f4e 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -251,7 +251,7 @@ ENTRY(sys_call_table) .long sys_io_submit .long sys_io_cancel .long sys_fadvise64 /* 250 */ - .long sys_set_zone_reclaim + .long sys_ni_syscall .long sys_exit_group .long sys_lookup_dcookie .long sys_epoll_create diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 66946f3fdac7..9be53e1ea404 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1573,7 +1573,7 @@ sys_call_table: data8 sys_keyctl data8 sys_ioprio_set data8 sys_ioprio_get // 1275 - data8 sys_set_zone_reclaim + data8 sys_ni_syscall data8 sys_inotify_init data8 sys_inotify_add_watch data8 sys_inotify_rm_watch diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 42b40ae5eada..1ab2370e2efa 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -79,7 +79,6 @@ cond_syscall(sys_request_key); cond_syscall(sys_keyctl); cond_syscall(compat_sys_keyctl); cond_syscall(compat_sys_socketcall); -cond_syscall(sys_set_zone_reclaim); cond_syscall(sys_inotify_init); cond_syscall(sys_inotify_add_watch); cond_syscall(sys_inotify_rm_watch); -- cgit v1.2.3 From 8dad46cf38c029248d1331b6a97b2999e0751cfa Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 1 Aug 2005 23:46:44 +0800 Subject: [PATCH] tridentfb: Fix scrolling artifacts if acceleration is enabled Reported by: Jochen Hein (Bugzilla Bug 4386) booting leaves the end of long lines in the last line on screen when scrolling. When X is running, scrolling puts garbage on the screen (looks like X data) Console switch fixes the screen. Behaviour seems to be identical with noaccel and without on the video=tridentfb parameter in lilo.conf. This bug was explained by: Knut_Petersen Acceleration is broken for all BLADE 3D chips for all versions of kernel 2.6 except for 32bit modes. Most important reason is that the u32 col parameter of the graphics engine needs the color value replicated to all u8 of the u32 (8bit modes) and to both u16 of the u32. Fix color value passed to graphics engine, verified by the reporter. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds --- drivers/video/tridentfb.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index da8004e5d03d..64aa78c5da79 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -454,13 +454,16 @@ static struct accel_switch accel_image = { static void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr) { int bpp = info->var.bits_per_pixel; - int col; + int col = 0; switch (bpp) { default: - case 8: col = fr->color; + case 8: col |= fr->color; + col |= col << 8; + col |= col << 16; break; case 16: col = ((u32 *)(info->pseudo_palette))[fr->color]; + break; case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; break; @@ -882,8 +885,9 @@ static int tridentfb_set_par(struct fb_info *info) write3X4(GraphEngReg, 0x80); //enable GE for text acceleration -// if (info->var.accel_flags & FB_ACCELF_TEXT) -//FIXME acc->init_accel(info->var.xres,bpp); +#ifdef CONFIG_FB_TRIDENT_ACCEL + acc->init_accel(info->var.xres,bpp); +#endif switch (bpp) { case 8: tmp = 0x00; break; @@ -981,12 +985,14 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green, t_outb(green>>10,0x3C9); t_outb(blue>>10,0x3C9); - } else - if (bpp == 16) /* RGB 565 */ - ((u32*)info->pseudo_palette)[regno] = (red & 0xF800) | - ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); - else - if (bpp == 32) /* ARGB 8888 */ + } else if (bpp == 16) { /* RGB 565 */ + u32 col; + + col = (red & 0xF800) | ((green & 0xFC00) >> 5) | + ((blue & 0xF800) >> 11); + col |= col << 16; + ((u32 *)(info->pseudo_palette))[regno] = col; + } else if (bpp == 32) /* ARGB 8888 */ ((u32*)info->pseudo_palette)[regno] = ((transp & 0xFF00) <<16) | ((red & 0xFF00) << 8) | -- cgit v1.2.3 From 8d894c47975f7222c5537e450e71310b395488c7 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 1 Aug 2005 23:51:34 +0800 Subject: [PATCH] tridentfb: Fix scrolling artifacts during disk IO Reported by: Jochen Hein (Bugzilla Bug 4312) When there is disk I/O happening, the framebuffer has a little snow on the screen. Once I/O has finished, no garbage remains on screen. This bug was explained by: Knut Petersen Most important is CRTC register 2f, signal quality is also improved for higher vclk values by changing set_vclk() according to the X drivers and cyblafb.c The fix is to set the performance register (0x2f) with a more stable value. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds --- drivers/video/tridentfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 64aa78c5da79..698ca9232e73 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -904,7 +904,7 @@ static int tridentfb_set_par(struct fb_info *info) write3X4(DRAMControl, tmp); //both IO,linear enable write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40); - write3X4(Performance,0x20); + write3X4(Performance,0x92); write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable /* convert from picoseconds to MHz */ -- cgit v1.2.3 From 4ceb5db9757aaeadcf8fbbf97d76bd42aa4df0d6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 1 Aug 2005 11:14:49 -0700 Subject: Fix get_user_pages() race for write access There's no real guarantee that handle_mm_fault() will always be able to break a COW situation - if an update from another thread ends up modifying the page table some way, handle_mm_fault() may end up requiring us to re-try the operation. That's normally fine, but get_user_pages() ended up re-trying it as a read, and thus a write access could in theory end up losing the dirty bit or be done on a page that had not been properly COW'ed. This makes get_user_pages() always retry write accesses as write accesses by making "follow_page()" require that a writable follow has the dirty bit set. That simplifies the code and solves the race: if the COW break fails for some reason, we'll just loop around and try again. Signed-off-by: Linus Torvalds --- mm/memory.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 6fe77acbc1cd..4e1c673784db 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -811,18 +811,15 @@ static struct page *__follow_page(struct mm_struct *mm, unsigned long address, pte = *ptep; pte_unmap(ptep); if (pte_present(pte)) { - if (write && !pte_write(pte)) + if (write && !pte_dirty(pte)) goto out; if (read && !pte_read(pte)) goto out; pfn = pte_pfn(pte); if (pfn_valid(pfn)) { page = pfn_to_page(pfn); - if (accessed) { - if (write && !pte_dirty(pte) &&!PageDirty(page)) - set_page_dirty(page); + if (accessed) mark_page_accessed(page); - } return page; } } @@ -941,10 +938,9 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, spin_lock(&mm->page_table_lock); do { struct page *page; - int lookup_write = write; cond_resched_lock(&mm->page_table_lock); - while (!(page = follow_page(mm, start, lookup_write))) { + while (!(page = follow_page(mm, start, write))) { /* * Shortcut for anonymous pages. We don't want * to force the creation of pages tables for @@ -952,8 +948,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, * nobody touched so far. This is important * for doing a core dump for these mappings. */ - if (!lookup_write && - untouched_anonymous_page(mm,vma,start)) { + if (!write && untouched_anonymous_page(mm,vma,start)) { page = ZERO_PAGE(start); break; } @@ -972,14 +967,6 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, default: BUG(); } - /* - * Now that we have performed a write fault - * and surely no longer have a shared page we - * shouldn't write, we shouldn't ignore an - * unwritable page in the page table if - * we are forcing write access. - */ - lookup_write = write && !force; spin_lock(&mm->page_table_lock); } if (pages) { -- cgit v1.2.3 From 697a2d63a3844caaa2b6565ab7f3d69086af94d4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 1 Aug 2005 12:37:54 -0700 Subject: Revert ACPI interrupt resume changes If there are devices that use interrupts over a suspend event, ACPI must restore the PCI interrupt links on resume. Anything else breaks any device that hasn't been converted to the new (dubious) PM rules. Drivers that need the irq free/re-aquire sequence can be done one by one independently of this one. --- drivers/acpi/pci_link.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 6a29610edc11..d9a9b86ecb28 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -776,15 +776,25 @@ end: } static int -irqrouter_suspend( - struct sys_device *dev, - u32 state) +acpi_pci_link_resume( + struct acpi_pci_link *link) +{ + ACPI_FUNCTION_TRACE("acpi_pci_link_resume"); + + if (link->refcnt && link->irq.active && link->irq.initialized) + return_VALUE(acpi_pci_link_set(link, link->irq.active)); + else + return_VALUE(0); +} + +static int +irqrouter_resume( + struct sys_device *dev) { struct list_head *node = NULL; struct acpi_pci_link *link = NULL; - int ret = 0; - ACPI_FUNCTION_TRACE("irqrouter_suspend"); + ACPI_FUNCTION_TRACE("irqrouter_resume"); list_for_each(node, &acpi_link.entries) { link = list_entry(node, struct acpi_pci_link, node); @@ -793,21 +803,9 @@ irqrouter_suspend( "Invalid link context\n")); continue; } - if (link->irq.initialized && link->refcnt != 0 - /* We ignore legacy IDE device irq */ - && link->irq.active != 14 && link->irq.active !=15) { - printk(KERN_WARNING PREFIX - "%d drivers with interrupt %d neglected to call" - " pci_disable_device at .suspend\n", - link->refcnt, - link->irq.active); - printk(KERN_WARNING PREFIX - "Fix the driver, or rmmod before suspend\n"); - link->refcnt = 0; - ret = -EINVAL; - } + acpi_pci_link_resume(link); } - return_VALUE(ret); + return_VALUE(0); } @@ -922,7 +920,7 @@ __setup("acpi_irq_balance", acpi_irq_balance_set); /* FIXME: we will remove this interface after all drivers call pci_disable_device */ static struct sysdev_class irqrouter_sysdev_class = { set_kset_name("irqrouter"), - .suspend = irqrouter_suspend, + .resume = irqrouter_resume, }; -- cgit v1.2.3 From de5b31101fdefab2a7858a17601c1a35aadf237f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 31 Jul 2005 22:34:40 -0700 Subject: [PATCH] i2c-mpc.c: revert duplicate patch Seems that both Greg and I submitted the same patch and it just kept on applying... Cc: Greg KH Cc: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/i2c/busses/i2c-mpc.c | 94 -------------------------------------------- 1 file changed, 94 deletions(-) diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 04adde62a003..9ad3e9262e8a 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -382,100 +382,6 @@ static void __exit fsl_i2c_exit(void) module_init(fsl_i2c_init); module_exit(fsl_i2c_exit); -static int fsl_i2c_probe(struct device *device) -{ - int result = 0; - struct mpc_i2c *i2c; - struct platform_device *pdev = to_platform_device(device); - struct fsl_i2c_platform_data *pdata; - struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data; - - if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) { - return -ENOMEM; - } - memset(i2c, 0, sizeof(*i2c)); - - i2c->irq = platform_get_irq(pdev, 0); - i2c->flags = pdata->device_flags; - init_waitqueue_head(&i2c->queue); - - i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION); - - if (!i2c->base) { - printk(KERN_ERR "i2c-mpc - failed to map controller\n"); - result = -ENOMEM; - goto fail_map; - } - - if (i2c->irq != 0) - if ((result = request_irq(i2c->irq, mpc_i2c_isr, - SA_SHIRQ, "i2c-mpc", i2c)) < 0) { - printk(KERN_ERR - "i2c-mpc - failed to attach interrupt\n"); - goto fail_irq; - } - - mpc_i2c_setclock(i2c); - dev_set_drvdata(device, i2c); - - i2c->adap = mpc_ops; - i2c_set_adapdata(&i2c->adap, i2c); - i2c->adap.dev.parent = &pdev->dev; - if ((result = i2c_add_adapter(&i2c->adap)) < 0) { - printk(KERN_ERR "i2c-mpc - failed to add adapter\n"); - goto fail_add; - } - - return result; - - fail_add: - if (i2c->irq != 0) - free_irq(i2c->irq, NULL); - fail_irq: - iounmap(i2c->base); - fail_map: - kfree(i2c); - return result; -}; - -static int fsl_i2c_remove(struct device *device) -{ - struct mpc_i2c *i2c = dev_get_drvdata(device); - - i2c_del_adapter(&i2c->adap); - dev_set_drvdata(device, NULL); - - if (i2c->irq != 0) - free_irq(i2c->irq, i2c); - - iounmap(i2c->base); - kfree(i2c); - return 0; -}; - -/* Structure for a device driver */ -static struct device_driver fsl_i2c_driver = { - .name = "fsl-i2c", - .bus = &platform_bus_type, - .probe = fsl_i2c_probe, - .remove = fsl_i2c_remove, -}; - -static int __init fsl_i2c_init(void) -{ - return driver_register(&fsl_i2c_driver); -} - -static void __exit fsl_i2c_exit(void) -{ - driver_unregister(&fsl_i2c_driver); -} - -module_init(fsl_i2c_init); -module_exit(fsl_i2c_exit); - MODULE_AUTHOR("Adrian Cox "); MODULE_DESCRIPTION ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors"); -- cgit v1.2.3 From 3fef3fa24d8d1bb6d82cad195f73917fa6534dac Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 31 Jul 2005 22:34:40 -0700 Subject: [PATCH] skge build fix Make it compile with CONFIG_PM=n Cc: "Rafael J. Wysocki" Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/sk98lin/skge.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 49bd8c7c3f7d..6ee4771addf1 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -5206,6 +5206,9 @@ static int skge_resume(struct pci_dev *pdev) return 0; } +#else +#define skge_suspend NULL +#define skge_resume NULL #endif static struct pci_device_id skge_pci_tbl[] = { -- cgit v1.2.3 From cdf32eaa4e601b15146e21b6470de00f149ce37f Mon Sep 17 00:00:00 2001 From: Eric Lammerts Date: Sun, 31 Jul 2005 22:34:42 -0700 Subject: [PATCH] disable addres space randomization default on transmeta CPUs We know that the randomisation slows down some workloads on Transmeta CPUs by quite large amounts. We think it's because the CPU needs to recode the same x86 instructions when they pop up at a different virtual address after a fork+exec. So disable randomization by default on those CPUs. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/transmeta.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c index f57e5ee94943..d8e59e198675 100644 --- a/arch/i386/kernel/cpu/transmeta.c +++ b/arch/i386/kernel/cpu/transmeta.c @@ -76,6 +76,10 @@ static void __init init_transmeta(struct cpuinfo_x86 *c) #define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV) if ( c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686 ) c->x86 = 6; + + /* randomize_va_space slows us down enormously; + it probably triggers retranslation of x86->native bytecode */ + randomize_va_space = 0; } static void transmeta_identify(struct cpuinfo_x86 * c) -- cgit v1.2.3 From fd3113e84e188781aa2935fbc4351d64ccdd171b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 31 Jul 2005 22:34:43 -0700 Subject: [PATCH] V4L: Miscellaneous fixes - Fixed some bttv card numbers. - BTTV and SAA7134 version numbers incremented to reflect changes. - pci_dma_supported() is called after pci_set_dma_mask() which already did check that for us. This patch removes the unneeded call to pci_dma_supported() at bttv-driver.c - Ensure a sufficient I2C bus idle time between 2 messages for saa7134-i2c.c - It is important to write at first to MO_GP3_IO for cx88-tvaudio.c - Use try_to_freeze() instead of refrigerator at msp3400.c - Recognizing the MFPE05-2 Tuner at tveeprom.c - Add new parameter to help identify radio chipsets at tuner module: show_i2c=1 will show 16 reading bytes from detected tuners. - BTTV does generate some Unimplemented IOCTL log at tuner module: 0x40046d11(dir=1,tp=0x6d,nr=17,sz=4) means that it is sending MSP3400 calls to non-msp3400 tuners. Warning eliminated. VIDIOSAUDIO is also called, so debug messages updated. It is still requiring IOCTL implementation. - Added two more tuners. - Add support for the SVideo input on the GDI Black Gold. Signed-off-by: Peter Missel Signed-off-by: Graham Bevan Signed-off-by: Torsten Seeboth Signed-off-by: Hartmut Hackmann Signed-off-by: Tobias Klauser Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.tuner | 2 ++ drivers/media/video/bttv-driver.c | 7 +------ drivers/media/video/bttv.h | 6 ++++-- drivers/media/video/bttvp.h | 4 ++-- drivers/media/video/cx88/cx88-cards.c | 5 ++++- drivers/media/video/cx88/cx88-video.c | 4 ++-- drivers/media/video/msp3400.c | 4 +--- drivers/media/video/saa7134/saa7134-i2c.c | 4 +++- drivers/media/video/saa7134/saa7134.h | 4 ++-- drivers/media/video/tea5767.c | 15 ++++++++------- drivers/media/video/tuner-core.c | 29 ++++++++++++++++++++++++++++- drivers/media/video/tuner-simple.c | 8 +++++++- drivers/media/video/tveeprom.c | 2 +- include/media/tuner.h | 4 +++- 14 files changed, 68 insertions(+), 30 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index d1b9d21ffd89..f3302e1b1b9c 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -62,3 +62,5 @@ tuner=60 - Thomson DDT 7611 (ATSC/NTSC) tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF tuner=62 - Philips TEA5767HN FM Radio tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner +tuner=64 - LG TDVS-H062F/TUA6034 +tuner=65 - Ymec TVF66T5-B/DFF diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 51a0f6d68e73..67f331eeeb19 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1,5 +1,5 @@ /* - $Id: bttv-driver.c,v 1.42 2005/07/05 17:37:35 nsh Exp $ + $Id: bttv-driver.c,v 1.45 2005/07/20 19:43:24 mkrufky Exp $ bttv - Bt848 frame grabber driver @@ -3869,11 +3869,6 @@ static int __devinit bttv_probe(struct pci_dev *dev, pci_set_master(dev); pci_set_command(dev); pci_set_drvdata(dev,btv); - if (!pci_dma_supported(dev,0xffffffff)) { - printk("bttv%d: Oops: no 32bit PCI DMA ???\n", btv->c.nr); - result = -EIO; - goto fail1; - } pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 191eaf1714ba..f2af9e1454f0 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -1,5 +1,5 @@ /* - * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $ + * $Id: bttv.h,v 1.22 2005/07/28 18:41:21 mchehab Exp $ * * bttv - Bt848 frame grabber driver * @@ -135,7 +135,9 @@ #define BTTV_DVICO_DVBT_LITE 0x80 #define BTTV_TIBET_CS16 0x83 #define BTTV_KODICOM_4400R 0x84 -#define BTTV_ADLINK_RTV24 0x85 +#define BTTV_ADLINK_RTV24 0x86 +#define BTTV_DVICO_FUSIONHDTV_5_LITE 0x87 +#define BTTV_ACORP_Y878F 0x88 /* i2c address list */ #define I2C_TSA5522 0xc2 diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index f3293e4a15ad..aab094bc243d 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -1,5 +1,5 @@ /* - $Id: bttvp.h,v 1.19 2005/06/16 21:38:45 nsh Exp $ + $Id: bttvp.h,v 1.21 2005/07/15 21:44:14 mchehab Exp $ bttv - Bt848 frame grabber driver @@ -27,7 +27,7 @@ #define _BTTVP_H_ #include -#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,15) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,16) #include #include diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 3d0c784b376f..293377a3972f 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-cards.c,v 1.86 2005/07/14 03:06:43 mchehab Exp $ + * $Id: cx88-cards.c,v 1.90 2005/07/28 02:47:42 mkrufky Exp $ * * device driver for Conexant 2388x based TV cards * card-specific stuff. @@ -90,6 +90,9 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, }}, }, [CX88_BOARD_PIXELVIEW] = { diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 5588a3aeecb4..5f58c103198a 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-video.c,v 1.80 2005/07/13 08:49:08 mchehab Exp $ + * $Id: cx88-video.c,v 1.82 2005/07/22 05:13:34 mkrufky Exp $ * * device driver for Conexant 2388x based TV cards * video4linux video interface @@ -758,10 +758,10 @@ static int video_open(struct inode *inode, struct file *file) struct cx88_core *core = dev->core; int board = core->board; dprintk(1,"video_open: setting radio device\n"); + cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0); cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1); cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2); - cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); dev->core->tvaudio = WW_FM; cx88_set_tvaudio(core); cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 6239254db27e..62f1b8ddb98b 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -741,11 +741,9 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout) schedule_timeout(msecs_to_jiffies(timeout)); } } - if (current->flags & PF_FREEZE) { - refrigerator (); - } remove_wait_queue(&msp->wq, &wait); + try_to_freeze(); return msp->restart; } diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 93dd61978541..1203b93a572c 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -1,5 +1,5 @@ /* - * $Id: saa7134-i2c.c,v 1.19 2005/07/07 01:49:30 mkrufky Exp $ + * $Id: saa7134-i2c.c,v 1.22 2005/07/22 04:09:41 mkrufky Exp $ * * device driver for philips saa7134 based TV cards * i2c interface support @@ -300,6 +300,8 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, status = i2c_get_status(dev); if (i2c_is_error(status)) goto err; + /* ensure that the bus is idle for at least one bit slot */ + msleep(1); d1printk("\n"); return num; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 6836c07794fc..2af0cb2a731b 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -1,5 +1,5 @@ /* - * $Id: saa7134.h,v 1.48 2005/07/01 08:22:24 nsh Exp $ + * $Id: saa7134.h,v 1.49 2005/07/13 17:25:25 mchehab Exp $ * * v4l2 device driver for philips saa7134 based TV cards * @@ -21,7 +21,7 @@ */ #include -#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13) +#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,14) #include #include diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 4d27ac1b7fb8..c8fd4204cd0a 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -2,7 +2,7 @@ * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview * I2C address is allways 0xC0. * - * $Id: tea5767.c,v 1.21 2005/07/14 03:06:43 mchehab Exp $ + * $Id: tea5767.c,v 1.26 2005/07/27 12:00:36 mkrufky Exp $ * * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) * This code is placed under the terms of the GNU General Public License @@ -15,7 +15,6 @@ #include #include #include -#include #define PREFIX "TEA5767 " @@ -293,7 +292,7 @@ static int tea5767_stereo(struct i2c_client *c) int tea5767_autodetection(struct i2c_client *c) { - unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff }; + unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; int rc; struct tuner *t = i2c_get_clientdata(c); @@ -302,7 +301,7 @@ int tea5767_autodetection(struct i2c_client *c) return EINVAL; } - /* If all bytes are the same then it's a TV tuner and not a tea5767 chip. */ + /* If all bytes are the same then it's a TV tuner and not a tea5767 */ if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && buffer[0] == buffer[3] && buffer[0] == buffer[4]) { tuner_warn("All bytes are equal. It is not a TEA5767\n"); @@ -318,6 +317,11 @@ int tea5767_autodetection(struct i2c_client *c) tuner_warn("Chip ID is not zero. It is not a TEA5767\n"); return EINVAL; } + /* It seems that tea5767 returns 0xff after the 5th byte */ + if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { + tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n"); + return EINVAL; + } tuner_warn("TEA5767 detected.\n"); return 0; @@ -327,9 +331,6 @@ int tea5767_tuner_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - if (tea5767_autodetection(c) == EINVAL) - return EINVAL; - tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio"); strlcpy(c->name, "tea5767", sizeof(c->name)); diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index b25a9c08ac02..f0a579827a24 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -1,5 +1,5 @@ /* - * $Id: tuner-core.c,v 1.58 2005/07/14 03:06:43 mchehab Exp $ + * $Id: tuner-core.c,v 1.63 2005/07/28 18:19:55 mchehab Exp $ * * i2c tv tuner chip device driver * core core, i.e. kernel interfaces, registering and so on @@ -23,6 +23,8 @@ #include #include +#include "msp3400.h" + #define UNSET (-1U) /* standard i2c insmod options */ @@ -42,6 +44,9 @@ module_param(addr, int, 0444); static unsigned int no_autodetect = 0; module_param(no_autodetect, int, 0444); +static unsigned int show_i2c = 0; +module_param(show_i2c, int, 0444); + /* insmod options used at runtime => read/write */ unsigned int tuner_debug = 0; module_param(tuner_debug, int, 0644); @@ -320,6 +325,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); + if (show_i2c) { + unsigned char buffer[16]; + int i,rc; + + memset(buffer, 0, sizeof(buffer)); + rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer)); + printk("tuner-%04x I2C RECV = ",addr); + for (i=0;i Date: Sun, 31 Jul 2005 22:34:46 -0700 Subject: [PATCH] v4l: cx88 card support and documentation finishing touches Peter Missel: - Add support for the SVideo input on the GDI Black Gold. Mauro Carvalho Chehab: - Linux/version.h removed. Replaced by linux/utsname.h Michael Krufky: - Added analog support for DViCO FusionHDTV5 Gold. CC: Peter Missel Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 28 ++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 6d44958289de..03deb0726aa4 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -29,3 +29,4 @@ card=27 - PixelView PlayTV Ultra Pro (Stereo) card=28 - DViCO FusionHDTV 3 Gold-T card=29 - ADS Tech Instant TV DVB-T PCI card=30 - TerraTec Cinergy 1400 DVB-T +card=31 - DViCO FusionHDTV 5 Gold diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 293377a3972f..ebf02a7f81e8 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -499,6 +499,9 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, }}, .dvb = 1, }, @@ -756,6 +759,27 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, + [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = { + .name = "DViCO FusionHDTV 5 Gold", + .tuner_type = TUNER_LG_TDVS_H062F, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* See DViCO FusionHDTV 3 Gold-Q for GPIO documentation. */ + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0f0d, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0f00, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x0f00, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -883,6 +907,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x153b, .subdevice = 0x1166, .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1, + },{ + .subvendor = 0x18ac, + .subdevice = 0xd500, + .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index b008f7db6dfd..da65dc92787c 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -1,5 +1,5 @@ /* - * $Id: cx88.h,v 1.69 2005/07/13 17:25:25 mchehab Exp $ + * $Id: cx88.h,v 1.70 2005/07/24 17:44:09 mkrufky Exp $ * * v4l2 device driver for cx2388x based TV cards * @@ -171,6 +171,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28 #define CX88_BOARD_ADSTECH_DVB_T_PCI 29 #define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30 +#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From faf1668c954d24285d7b213cf1ff38fe93569f01 Mon Sep 17 00:00:00 2001 From: Michael Kerrisk Date: Sun, 31 Jul 2005 22:34:47 -0700 Subject: [PATCH] MAINTAINERS record -- MAN-PAGES Michael maintains the kernel manpages. He wants us to tell him when we change or augment the userspace API. Add his contact details to MAINTAINERS. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ec8433c39dee..c31ddc4bcdd6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1521,6 +1521,12 @@ P: Zach Brown M: zab@zabbo.net S: Odd Fixes +MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 +P: Michael Kerrisk +M: mtk-manpages@gmx.net +W: ftp://ftp.kernel.org/pub/linux/docs/manpages +S: Maintained + MARVELL MV64340 ETHERNET DRIVER P: Manish Lachwani M: Manish_Lachwani@pmc-sierra.com -- cgit v1.2.3 From 1caf1f0f187d99eb898bdc216de5a761740fe814 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Sun, 31 Jul 2005 22:34:48 -0700 Subject: [PATCH] plug MAN-PAGES maintainer in Documentation/SubmittingPatches Improve the likelihood that someone submitting a patch will notify the MAN-PAGES maintainer. This is a follow-up to comments on the July 29 lkml email thread: "Broke nice range for RLIMIT NICE" Signed-off-by: Paul Jackson Cc: "Michael Kerrisk" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/SubmittingPatches | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 6761a7b241a5..7f43b040311e 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -149,6 +149,11 @@ USB, framebuffer devices, the VFS, the SCSI subsystem, etc. See the MAINTAINERS file for a mailing list that relates specifically to your change. +If changes affect userland-kernel interfaces, please send +the MAN-PAGES maintainer (as listed in the MAINTAINERS file) +a man-pages patch, or at least a notification of the change, +so that some information makes its way into the manual pages. + Even if the maintainer did not respond in step #4, make sure to ALWAYS copy the maintainer when you change their code. -- cgit v1.2.3 From 57ee67af35183c60e924ebb6d6b3e1d2d9c03366 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 31 Jul 2005 22:34:49 -0700 Subject: [PATCH] ppc64: Fix CONFIG_ALTIVEC not set The code that sets the altivec capability of the CPU based on firmware informations can enable altivec when the kernel has CONFIG_ALTIVEC disabled. This results in "interesting" crashes. Signed-off-by: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/prom.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 47727a6f7346..5aca01ddd81f 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -916,6 +916,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, } } +#ifdef CONFIG_ALTIVEC /* Check if we have a VMX and eventually update CPU features */ prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL); if (prop && (*prop) > 0) { @@ -929,6 +930,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; } +#endif /* CONFIG_ALTIVEC */ /* * Check for an SMT capable CPU and set the CPU feature. We do -- cgit v1.2.3 From b1581566183f310abbd2d384a9079d4039faca05 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 31 Jul 2005 22:34:50 -0700 Subject: [PATCH] md: make sure raid5/raid6 resync uses correct 'max_sectors' The default resync_max_sector is set to "mddev->size << 1". If the raid-personality-module updates mddev->size, it must update resync_max_sectors too. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 1 + drivers/md/raid6main.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 4698d5f79575..43f231a467d5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1653,6 +1653,7 @@ static int run (mddev_t *mddev) /* device size must be a multiple of chunk size */ mddev->size &= ~(mddev->chunk_size/1024 -1); + mddev->resync_max_sectors = mddev->size << 1; if (!conf->chunk_size || conf->chunk_size % 4) { printk(KERN_ERR "raid5: invalid chunk size %d for %s\n", diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index f5ee16805111..495dee1d1e83 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -1813,6 +1813,7 @@ static int run (mddev_t *mddev) /* device size must be a multiple of chunk size */ mddev->size &= ~(mddev->chunk_size/1024 -1); + mddev->resync_max_sectors = mddev->size << 1; if (conf->raid_disks < 4) { printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n", -- cgit v1.2.3 From 01bdc0336f8f42b32b9be9ace7775329b25202a5 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sun, 31 Jul 2005 22:34:50 -0700 Subject: [PATCH] silence cs89x0 cs89x0 talks a lot at boot. Seems like debug leftover. This patch downgrades printks to KERN_DEBUG. While we're at it, make these messages a bit less obscure. Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/cs89x0.c | 12 ++++++++---- drivers/net/cs89x0.h | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 2c6dc24c3728..b780307093eb 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -417,6 +417,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) struct net_local *lp = netdev_priv(dev); static unsigned version_printed; int i; + int tmp; unsigned rev_type = 0; int eeprom_buff[CHKSUM_LEN]; int retval; @@ -492,14 +493,17 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) goto out2; } } -printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT)); + printk(KERN_DEBUG "PP_addr at %x: 0x%x\n", + ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT)); ioaddr &= ~3; outw(PP_ChipID, ioaddr + ADD_PORT); - if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) { - printk(KERN_ERR "%s: incorrect signature 0x%x\n", - dev->name, inw(ioaddr + DATA_PORT)); + tmp = inw(ioaddr + DATA_PORT); + if (tmp != CHIP_EISA_ID_SIG) { + printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!=" + CHIP_EISA_ID_SIG_STR "\n", + dev->name, ioaddr + DATA_PORT, tmp); retval = -ENODEV; goto out2; } diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h index bd3ad8e6cce9..decea264f121 100644 --- a/drivers/net/cs89x0.h +++ b/drivers/net/cs89x0.h @@ -93,6 +93,7 @@ #endif #define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */ +#define CHIP_EISA_ID_SIG_STR "0x630E" #ifdef IBMEIPKT #define EISA_ID_SIG 0x4D24 /* IBM */ -- cgit v1.2.3 From e8be1c8e065691c332fd8e9bae70c7096a69c31d Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sun, 31 Jul 2005 22:34:51 -0700 Subject: [PATCH] ppc32: Mark boards that don't build as BROKEN Marked APUS and GEMINI as BROKEN since they do not build at the platform level. We have requested that the maintainers of these boards/platforms fix them by the time 2.6.15 is released or we plan on concerning them unmaintained and thus removing them. Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 2c2da9b43b7a..f6db3b385fea 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -558,6 +558,7 @@ config PPC_MULTIPLATFORM config APUS bool "Amiga-APUS" + depends on BROKEN help Select APUS if configuring for a PowerUP Amiga. More information is available at: @@ -647,6 +648,7 @@ config PAL4 config GEMINI bool "Synergy-Gemini" + depends on BROKEN help Select Gemini if configuring for a Synergy Microsystems' Gemini series Single Board Computer. More information is available at: -- cgit v1.2.3 From c9cf73aee140baa425429902aaed2c758401343f Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Sun, 31 Jul 2005 22:34:52 -0700 Subject: [PATCH] ppc32: add 440ep support Add PPC440EP core support. PPC440EP is a PPC440-based SoC with a classic PPC FPU and another set of peripherals. Signed-off-by: Wade Farnsworth Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/boot/simple/Makefile | 6 ++ arch/ppc/boot/simple/pibs.c | 4 +- arch/ppc/kernel/cputable.c | 20 ++++ arch/ppc/kernel/entry.S | 1 + arch/ppc/kernel/head_44x.S | 12 +++ arch/ppc/kernel/misc.S | 1 + arch/ppc/platforms/4xx/Kconfig | 20 +++- arch/ppc/platforms/4xx/Makefile | 2 + arch/ppc/platforms/4xx/ibm440ep.c | 220 ++++++++++++++++++++++++++++++++++++++ arch/ppc/platforms/4xx/ibm440ep.h | 76 +++++++++++++ arch/ppc/syslib/Makefile | 2 + arch/ppc/syslib/ibm440gx_common.c | 15 +++ arch/ppc/syslib/ibm44x_common.h | 4 + include/asm-ppc/ibm44x.h | 34 +++++- include/asm-ppc/ibm4xx.h | 4 + include/asm-ppc/ppc_asm.h | 6 ++ 16 files changed, 421 insertions(+), 6 deletions(-) create mode 100644 arch/ppc/platforms/4xx/ibm440ep.c create mode 100644 arch/ppc/platforms/4xx/ibm440ep.h diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile index 991b4cbb83c8..d4dc4fa79647 100644 --- a/arch/ppc/boot/simple/Makefile +++ b/arch/ppc/boot/simple/Makefile @@ -61,6 +61,12 @@ zimageinitrd-$(CONFIG_IBM_OPENBIOS) := zImage.initrd-TREE end-$(CONFIG_EMBEDDEDBOOT) := embedded misc-$(CONFIG_EMBEDDEDBOOT) := misc-embedded.o + zimage-$(CONFIG_BAMBOO) := zImage-TREE +zimageinitrd-$(CONFIG_BAMBOO) := zImage.initrd-TREE + end-$(CONFIG_BAMBOO) := bamboo + entrypoint-$(CONFIG_BAMBOO) := 0x01000000 + extra.o-$(CONFIG_BAMBOO) := pibs.o + zimage-$(CONFIG_EBONY) := zImage-TREE zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE end-$(CONFIG_EBONY) := ebony diff --git a/arch/ppc/boot/simple/pibs.c b/arch/ppc/boot/simple/pibs.c index 1348740e503f..67222d57c345 100644 --- a/arch/ppc/boot/simple/pibs.c +++ b/arch/ppc/boot/simple/pibs.c @@ -91,9 +91,11 @@ load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, mac64 = simple_strtoull((char *)PIBS_MAC_BASE, 0, 16); memcpy(hold_residual->bi_enetaddr, (char *)&mac64+2, 6); -#ifdef CONFIG_440GX +#if defined(CONFIG_440GX) || defined(CONFIG_440EP) mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET), 0, 16); memcpy(hold_residual->bi_enet1addr, (char *)&mac64+2, 6); +#endif +#ifdef CONFIG_440GX mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*2), 0, 16); memcpy(hold_residual->bi_enet2addr, (char *)&mac64+2, 6); mac64 = simple_strtoull((char *)(PIBS_MAC_BASE+PIBS_MAC_OFFSET*3), 0, 16); diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c index 50936cda0af9..8a3d74f2531e 100644 --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c @@ -852,6 +852,26 @@ struct cpu_spec cpu_specs[] = { #endif /* CONFIG_40x */ #ifdef CONFIG_44x + { + .pvr_mask = 0xf0000fff, + .pvr_value = 0x40000850, + .cpu_name = "440EP Rev. A", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { + .pvr_mask = 0xf0000fff, + .pvr_value = 0x400008d3, + .cpu_name = "440EP Rev. B", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = COMMON_PPC, /* 440EP has an FPU */ + .icache_bsize = 32, + .dcache_bsize = 32, + }, { /* 440GP Rev. B */ .pvr_mask = 0xf0000fff, .pvr_value = 0x40000440, diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index d4df68629cc6..cb83045e2edf 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -215,6 +215,7 @@ syscall_dotrace_cont: lwzx r10,r10,r0 /* Fetch system call handler [ptr] */ mtlr r10 addi r9,r1,STACK_FRAME_OVERHEAD + PPC440EP_ERR42 blrl /* Call handler */ .globl ret_from_syscall ret_from_syscall: diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 72ee8f33bde4..69ff3a9961e8 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -190,7 +190,9 @@ skpinv: addi r4,r4,1 /* Increment */ /* xlat fields */ lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */ +#ifndef CONFIG_440EP ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */ +#endif /* attrib fields */ li r5,0 @@ -228,6 +230,16 @@ skpinv: addi r4,r4,1 /* Increment */ lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ mtspr SPRN_IVPR,r4 +#ifdef CONFIG_440EP + /* Clear DAPUIB flag in CCR0 (enable APU between CPU and FPU) */ + mfspr r2,SPRN_CCR0 + lis r3,0xffef + ori r3,r3,0xffff + and r2,r2,r3 + mtspr SPRN_CCR0,r2 + isync +#endif + /* * This is where the main kernel code starts. */ diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index c2fb85b49a11..ce71b4a01585 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -1145,6 +1145,7 @@ _GLOBAL(kernel_thread) stwu r0,-16(r1) mtlr r30 /* fn addr in lr */ mr r3,r31 /* load arg and call fn */ + PPC440EP_ERR42 blrl li r0,__NR_exit /* exit if function returns */ li r3,0 diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index a0612a86455a..f7c045764e04 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -68,6 +68,11 @@ choice depends on 44x default EBONY +config BAMBOO + bool "Bamboo" + help + This option enables support for the IBM PPC440EP evaluation board. + config EBONY bool "Ebony" help @@ -98,6 +103,12 @@ config NP405H depends on ASH default y +config 440EP + bool + depends on BAMBOO + select PPC_FPU + default y + config 440GP bool depends on EBONY @@ -115,7 +126,7 @@ config 440SP config 440 bool - depends on 440GP || 440SP + depends on 440GP || 440SP || 440EP default y config 440A @@ -123,6 +134,11 @@ config 440A depends on 440GX default y +config IBM440EP_ERR42 + bool + depends on 440EP + default y + # All 405-based cores up until the 405GPR and 405EP have this errata. config IBM405_ERR77 bool @@ -142,7 +158,7 @@ config BOOKE config IBM_OCP bool - depends on ASH || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y config XILINX_OCP diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index ea470c6adbb6..844c3b5066e8 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -2,6 +2,7 @@ # Makefile for the PowerPC 4xx linux kernel. obj-$(CONFIG_ASH) += ash.o +obj-$(CONFIG_BAMBOO) += bamboo.o obj-$(CONFIG_CPCI405) += cpci405.o obj-$(CONFIG_EBONY) += ebony.o obj-$(CONFIG_EP405) += ep405.o @@ -19,6 +20,7 @@ obj-$(CONFIG_405GP) += ibm405gp.o obj-$(CONFIG_REDWOOD_5) += ibmstb4.o obj-$(CONFIG_NP405H) += ibmnp405h.o obj-$(CONFIG_REDWOOD_6) += ibmstbx25.o +obj-$(CONFIG_440EP) += ibm440ep.o obj-$(CONFIG_440GP) += ibm440gp.o obj-$(CONFIG_440GX) += ibm440gx.o obj-$(CONFIG_440SP) += ibm440sp.o diff --git a/arch/ppc/platforms/4xx/ibm440ep.c b/arch/ppc/platforms/4xx/ibm440ep.c new file mode 100644 index 000000000000..284da01f1ffd --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440ep.c @@ -0,0 +1,220 @@ +/* + * arch/ppc/platforms/4xx/ibm440ep.c + * + * PPC440EP I/O descriptions + * + * Wade Farnsworth + * Copyright 2004 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include +#include +#include +#include +#include + +static struct ocp_func_emac_data ibm440ep_emac0_def = { + .rgmii_idx = -1, /* No RGMII */ + .rgmii_mux = -1, /* No RGMII */ + .zmii_idx = 0, /* ZMII device index */ + .zmii_mux = 0, /* ZMII input of this EMAC */ + .mal_idx = 0, /* MAL device index */ + .mal_rx_chan = 0, /* MAL rx channel number */ + .mal_tx_chan = 0, /* MAL tx channel number */ + .wol_irq = 61, /* WOL interrupt number */ + .mdio_idx = -1, /* No shared MDIO */ + .tah_idx = -1, /* No TAH */ +}; + +static struct ocp_func_emac_data ibm440ep_emac1_def = { + .rgmii_idx = -1, /* No RGMII */ + .rgmii_mux = -1, /* No RGMII */ + .zmii_idx = 0, /* ZMII device index */ + .zmii_mux = 1, /* ZMII input of this EMAC */ + .mal_idx = 0, /* MAL device index */ + .mal_rx_chan = 1, /* MAL rx channel number */ + .mal_tx_chan = 2, /* MAL tx channel number */ + .wol_irq = 63, /* WOL interrupt number */ + .mdio_idx = -1, /* No shared MDIO */ + .tah_idx = -1, /* No TAH */ +}; +OCP_SYSFS_EMAC_DATA() + +static struct ocp_func_mal_data ibm440ep_mal0_def = { + .num_tx_chans = 4, /* Number of TX channels */ + .num_rx_chans = 2, /* Number of RX channels */ + .txeob_irq = 10, /* TX End Of Buffer IRQ */ + .rxeob_irq = 11, /* RX End Of Buffer IRQ */ + .txde_irq = 33, /* TX Descriptor Error IRQ */ + .rxde_irq = 34, /* RX Descriptor Error IRQ */ + .serr_irq = 32, /* MAL System Error IRQ */ +}; +OCP_SYSFS_MAL_DATA() + +static struct ocp_func_iic_data ibm440ep_iic0_def = { + .fast_mode = 0, /* Use standad mode (100Khz) */ +}; + +static struct ocp_func_iic_data ibm440ep_iic1_def = { + .fast_mode = 0, /* Use standad mode (100Khz) */ +}; +OCP_SYSFS_IIC_DATA() + +struct ocp_def core_ocp[] = { + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_OPB, + .index = 0, + .paddr = 0x0EF600000ULL, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 0, + .paddr = PPC440EP_UART0_ADDR, + .irq = UART0_INT, + .pm = IBM_CPM_UART0, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 1, + .paddr = PPC440EP_UART1_ADDR, + .irq = UART1_INT, + .pm = IBM_CPM_UART1, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 2, + .paddr = PPC440EP_UART2_ADDR, + .irq = UART2_INT, + .pm = IBM_CPM_UART2, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_16550, + .index = 3, + .paddr = PPC440EP_UART3_ADDR, + .irq = UART3_INT, + .pm = IBM_CPM_UART3, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_IIC, + .index = 0, + .paddr = 0x0EF600700ULL, + .irq = 2, + .pm = IBM_CPM_IIC0, + .additions = &ibm440ep_iic0_def, + .show = &ocp_show_iic_data + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_IIC, + .index = 1, + .paddr = 0x0EF600800ULL, + .irq = 7, + .pm = IBM_CPM_IIC1, + .additions = &ibm440ep_iic1_def, + .show = &ocp_show_iic_data + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_GPIO, + .index = 0, + .paddr = 0x0EF600B00ULL, + .irq = OCP_IRQ_NA, + .pm = IBM_CPM_GPIO0, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_GPIO, + .index = 1, + .paddr = 0x0EF600C00ULL, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_MAL, + .paddr = OCP_PADDR_NA, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + .additions = &ibm440ep_mal0_def, + .show = &ocp_show_mal_data, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_EMAC, + .index = 0, + .paddr = 0x0EF600E00ULL, + .irq = 60, + .pm = OCP_CPM_NA, + .additions = &ibm440ep_emac0_def, + .show = &ocp_show_emac_data, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_EMAC, + .index = 1, + .paddr = 0x0EF600F00ULL, + .irq = 62, + .pm = OCP_CPM_NA, + .additions = &ibm440ep_emac1_def, + .show = &ocp_show_emac_data, + }, + { .vendor = OCP_VENDOR_IBM, + .function = OCP_FUNC_ZMII, + .paddr = 0x0EF600D00ULL, + .irq = OCP_IRQ_NA, + .pm = OCP_CPM_NA, + }, + { .vendor = OCP_VENDOR_INVALID + } +}; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xffbffe03, + .triggering = 0xfffffe00, + .ext_irq_mask = 0x000001fc, /* IRQ0 - IRQ6 */ + }, + { .polarity = 0xffffc6ef, + .triggering = 0xffffc7ff, + .ext_irq_mask = 0x00003800, /* IRQ7 - IRQ9 */ + }, +}; + +static struct resource usb_gadget_resources[] = { + [0] = { + .start = 0x050000100ULL, + .end = 0x05000017FULL, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 55, + .end = 55, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 dma_mask = 0xffffffffULL; + +static struct platform_device usb_gadget_device = { + .name = "musbhsfc", + .id = 0, + .num_resources = ARRAY_SIZE(usb_gadget_resources), + .resource = usb_gadget_resources, + .dev = { + .dma_mask = &dma_mask, + .coherent_dma_mask = 0xffffffffULL, + } +}; + +static struct platform_device *ibm440ep_devs[] __initdata = { + &usb_gadget_device, +}; + +static int __init +ibm440ep_platform_add_devices(void) +{ + return platform_add_devices(ibm440ep_devs, ARRAY_SIZE(ibm440ep_devs)); +} +arch_initcall(ibm440ep_platform_add_devices); + diff --git a/arch/ppc/platforms/4xx/ibm440ep.h b/arch/ppc/platforms/4xx/ibm440ep.h new file mode 100644 index 000000000000..97c80b8e3e10 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440ep.h @@ -0,0 +1,76 @@ +/* + * arch/ppc/platforms/4xx/ibm440ep.h + * + * PPC440EP definitions + * + * Wade Farnsworth + * + * Copyright 2002 Roland Dreier + * Copyright 2004 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifdef __KERNEL__ +#ifndef __PPC_PLATFORMS_IBM440EP_H +#define __PPC_PLATFORMS_IBM440EP_H + +#include +#include + +/* UART */ +#define PPC440EP_UART0_ADDR 0x0EF600300 +#define PPC440EP_UART1_ADDR 0x0EF600400 +#define PPC440EP_UART2_ADDR 0x0EF600500 +#define PPC440EP_UART3_ADDR 0x0EF600600 +#define UART0_INT 0 +#define UART1_INT 1 +#define UART2_INT 3 +#define UART3_INT 4 + +/* Clock and Power Management */ +#define IBM_CPM_IIC0 0x80000000 /* IIC interface */ +#define IBM_CPM_IIC1 0x40000000 /* IIC interface */ +#define IBM_CPM_PCI 0x20000000 /* PCI bridge */ +#define IBM_CPM_USB1H 0x08000000 /* USB 1.1 Host */ +#define IBM_CPM_FPU 0x04000000 /* floating point unit */ +#define IBM_CPM_CPU 0x02000000 /* processor core */ +#define IBM_CPM_DMA 0x01000000 /* DMA controller */ +#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */ +#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */ +#define IBM_CPM_EBC 0x00200000 /* External Bus Controller */ +#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */ +#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */ +#define IBM_CPM_PLB4 0x00040000 /* PLB4 bus arbiter */ +#define IBM_CPM_PLB4x3 0x00020000 /* PLB4 to PLB3 bridge controller */ +#define IBM_CPM_PLB3x4 0x00010000 /* PLB3 to PLB4 bridge controller */ +#define IBM_CPM_PLB3 0x00008000 /* PLB3 bus arbiter */ +#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */ +#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */ +#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */ +#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */ +#define IBM_CPM_UART0 0x00000200 /* serial port 0 */ +#define IBM_CPM_UART1 0x00000100 /* serial port 1 */ +#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */ +#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */ +#define IBM_CPM_EMAC0 0x00000020 /* ethernet port 0 */ +#define IBM_CPM_EMAC1 0x00000010 /* ethernet port 1 */ +#define IBM_CPM_UART2 0x00000008 /* serial port 2 */ +#define IBM_CPM_UART3 0x00000004 /* serial port 3 */ +#define IBM_CPM_USB2D 0x00000002 /* USB 2.0 Device */ +#define IBM_CPM_USB2H 0x00000001 /* USB 2.0 Host */ + +#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC0 | IBM_CPM_UIC1 | IBM_CPM_CPU \ + | IBM_CPM_EBC | IBM_CPM_BGO | IBM_CPM_FPU \ + | IBM_CPM_EBM | IBM_CPM_PLB4 | IBM_CPM_3x4 \ + | IBM_CPM_PLB3 | IBM_CPM_PLB4x3 \ + | IBM_CPM_EMAC0 | IBM_CPM_TMRCLK \ + | IBM_CPM_DMA | IBM_CPM_PCI | IBM_CPM_EMAC1) + + +#endif /* __PPC_PLATFORMS_IBM440EP_H */ +#endif /* __KERNEL__ */ diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index dec5bf4f6879..220a65ab0a51 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o obj-$(CONFIG_PPC_OCP) += ocp.o obj-$(CONFIG_IBM_OCP) += ibm_ocp.o obj-$(CONFIG_44x) += ibm44x_common.o +obj-$(CONFIG_440EP) += ibm440gx_common.o obj-$(CONFIG_440GP) += ibm440gp_common.o obj-$(CONFIG_440GX) += ibm440gx_common.o obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o @@ -44,6 +45,7 @@ obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o todc_time.o obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \ todc_time.o +obj-$(CONFIG_BAMBOO) += indirect_pci.o pci_auto.o todc_time.o obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o obj-$(CONFIG_EV64260) += todc_time.o pci_auto.o diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c index 4ad85e0e0234..d4776af6a3ca 100644 --- a/arch/ppc/syslib/ibm440gx_common.c +++ b/arch/ppc/syslib/ibm440gx_common.c @@ -34,6 +34,10 @@ void __init ibm440gx_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk, u32 plld = CPR_READ(DCRN_CPR_PLLD); u32 uart0 = SDR_READ(DCRN_SDR_UART0); u32 uart1 = SDR_READ(DCRN_SDR_UART1); +#ifdef CONFIG_440EP + u32 uart2 = SDR_READ(DCRN_SDR_UART2); + u32 uart3 = SDR_READ(DCRN_SDR_UART3); +#endif /* Dividers */ u32 fbdv = __fix_zero((plld >> 24) & 0x1f, 32); @@ -96,6 +100,17 @@ bypass: p->uart1 = ser_clk; else p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256); +#ifdef CONFIG_440EP + if (uart2 & 0x00800000) + p->uart2 = ser_clk; + else + p->uart2 = p->plb / __fix_zero(uart2 & 0xff, 256); + + if (uart3 & 0x00800000) + p->uart3 = ser_clk; + else + p->uart3 = p->plb / __fix_zero(uart3 & 0xff, 256); +#endif } /* Issue L2C diagnostic command */ diff --git a/arch/ppc/syslib/ibm44x_common.h b/arch/ppc/syslib/ibm44x_common.h index b14eb603ce01..c16b6a5ac6ab 100644 --- a/arch/ppc/syslib/ibm44x_common.h +++ b/arch/ppc/syslib/ibm44x_common.h @@ -29,6 +29,10 @@ struct ibm44x_clocks { unsigned int ebc; /* PerClk */ unsigned int uart0; unsigned int uart1; +#ifdef CONFIG_440EP + unsigned int uart2; + unsigned int uart3; +#endif }; /* common 44x platform init */ diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h index 87f051138b9d..21e41c9b7267 100644 --- a/include/asm-ppc/ibm44x.h +++ b/include/asm-ppc/ibm44x.h @@ -35,8 +35,10 @@ #define PPC44x_LOW_SLOT 63 /* LS 32-bits of UART0 physical address location for early serial text debug */ -#ifdef CONFIG_440SP +#if defined(CONFIG_440SP) #define UART0_PHYS_IO_BASE 0xf0000200 +#elif defined(CONFIG_440EP) +#define UART0_PHYS_IO_BASE 0xe0000000 #else #define UART0_PHYS_IO_BASE 0x40000200 #endif @@ -49,11 +51,16 @@ /* * Standard 4GB "page" definitions */ -#ifdef CONFIG_440SP +#if defined(CONFIG_440SP) #define PPC44x_IO_PAGE 0x0000000100000000ULL #define PPC44x_PCICFG_PAGE 0x0000000900000000ULL #define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE #define PPC44x_PCIMEM_PAGE 0x0000000a00000000ULL +#elif defined(CONFIG_440EP) +#define PPC44x_IO_PAGE 0x0000000000000000ULL +#define PPC44x_PCICFG_PAGE 0x0000000000000000ULL +#define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE +#define PPC44x_PCIMEM_PAGE 0x0000000000000000ULL #else #define PPC44x_IO_PAGE 0x0000000100000000ULL #define PPC44x_PCICFG_PAGE 0x0000000200000000ULL @@ -64,7 +71,7 @@ /* * 36-bit trap ranges */ -#ifdef CONFIG_440SP +#if defined(CONFIG_440SP) #define PPC44x_IO_LO 0xf0000000UL #define PPC44x_IO_HI 0xf0000fffUL #define PPC44x_PCI0CFG_LO 0x0ec00000UL @@ -75,6 +82,13 @@ #define PPC44x_PCI2CFG_HI 0x2ec00007UL #define PPC44x_PCIMEM_LO 0x80000000UL #define PPC44x_PCIMEM_HI 0xdfffffffUL +#elif defined(CONFIG_440EP) +#define PPC44x_IO_LO 0xef500000UL +#define PPC44x_IO_HI 0xefffffffUL +#define PPC44x_PCI0CFG_LO 0xeec00000UL +#define PPC44x_PCI0CFG_HI 0xeecfffffUL +#define PPC44x_PCIMEM_LO 0xa0000000UL +#define PPC44x_PCIMEM_HI 0xdfffffffUL #else #define PPC44x_IO_LO 0x40000000UL #define PPC44x_IO_HI 0x40000fffUL @@ -152,6 +166,12 @@ #define DCRN_SDR_UART0 0x0120 #define DCRN_SDR_UART1 0x0121 +#ifdef CONFIG_440EP +#define DCRN_SDR_UART2 0x0122 +#define DCRN_SDR_UART3 0x0123 +#define DCRN_SDR_CUST0 0x4000 +#endif + /* SDR read/write helper macros */ #define SDR_READ(offset) ({\ mtdcr(DCRN_SDR_CONFIG_ADDR, offset); \ @@ -169,6 +189,14 @@ #define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ #define DCRN_MAL_BASE 0x180 +#ifdef CONFIG_440EP +#define DCRN_DMA2P40_BASE 0x300 +#define DCRN_DMA2P41_BASE 0x308 +#define DCRN_DMA2P42_BASE 0x310 +#define DCRN_DMA2P43_BASE 0x318 +#define DCRN_DMA2P4SR_BASE 0x320 +#endif + /* UIC */ #define DCRN_UIC0_BASE 0xc0 #define DCRN_UIC1_BASE 0xd0 diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h index 35260afa33a9..e807be96e981 100644 --- a/include/asm-ppc/ibm4xx.h +++ b/include/asm-ppc/ibm4xx.h @@ -97,6 +97,10 @@ void ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5, #elif CONFIG_44x +#if defined(CONFIG_BAMBOO) +#include +#endif + #if defined(CONFIG_EBONY) #include #endif diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h index f76221def484..bb53e2def363 100644 --- a/include/asm-ppc/ppc_asm.h +++ b/include/asm-ppc/ppc_asm.h @@ -186,6 +186,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) #define PPC405_ERR77_SYNC #endif +#ifdef CONFIG_IBM440EP_ERR42 +#define PPC440EP_ERR42 isync +#else +#define PPC440EP_ERR42 +#endif + /* The boring bits... */ /* Condition Register Bit Fields */ -- cgit v1.2.3 From 497799d368b2106c3266a20d75ff221eed068cad Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Sun, 31 Jul 2005 22:34:53 -0700 Subject: [PATCH] ppc32: add bamboo platform Add Bamboo platform support. This is an AMCC 440EP-based reference platform. Signed-off-by: Wade Farnsworth Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/platforms/4xx/bamboo.c | 427 ++++++++++++++++++++++++++++++++++++++++ arch/ppc/platforms/4xx/bamboo.h | 136 +++++++++++++ 2 files changed, 563 insertions(+) create mode 100644 arch/ppc/platforms/4xx/bamboo.c create mode 100644 arch/ppc/platforms/4xx/bamboo.h diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c new file mode 100644 index 000000000000..f116787b0b76 --- /dev/null +++ b/arch/ppc/platforms/4xx/bamboo.c @@ -0,0 +1,427 @@ +/* + * arch/ppc/platforms/4xx/bamboo.c + * + * Bamboo board specific routines + * + * Wade Farnsworth + * Copyright 2004 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * This is a horrible kludge, we eventually need to abstract this + * generic PHY stuff, so the standard phy mode defines can be + * easily used from arch code. + */ +#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h" + +bd_t __res; + +static struct ibm44x_clocks clocks __initdata; + +/* + * Bamboo external IRQ triggering/polarity settings + */ +unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ0: Ethernet transceiver */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ1: Expansion connector */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ2: PCI slot 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ3: PCI slot 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ4: PCI slot 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ5: PCI slot 3 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ6: SMI pushbutton */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ7: EXT */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ8: EXT */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ9: EXT */ +}; + +static void __init +bamboo_calibrate_decr(void) +{ + unsigned int freq; + + if (mfspr(SPRN_CCR1) & CCR1_TCS) + freq = BAMBOO_TMRCLK; + else + freq = clocks.cpu; + + ibm44x_calibrate_decr(freq); + +} + +static int +bamboo_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "vendor\t\t: IBM\n"); + seq_printf(m, "machine\t\t: PPC440EP EVB (Bamboo)\n"); + + return 0; +} + +static inline int +bamboo_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 28, 28, 28, 28 }, /* IDSEL 1 - PCI Slot 0 */ + { 27, 27, 27, 27 }, /* IDSEL 2 - PCI Slot 1 */ + { 26, 26, 26, 26 }, /* IDSEL 3 - PCI Slot 2 */ + { 25, 25, 25, 25 }, /* IDSEL 4 - PCI Slot 3 */ + }; + + const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +static void __init bamboo_set_emacdata(void) +{ + unsigned char * selection1_base; + struct ocp_def *def; + struct ocp_func_emac_data *emacdata; + u8 selection1_val; + int mode; + + selection1_base = ioremap64(BAMBOO_FPGA_SELECTION1_REG_ADDR, 16); + selection1_val = readb(selection1_base); + iounmap((void *) selection1_base); + if (BAMBOO_SEL_MII(selection1_val)) + mode = PHY_MODE_MII; + else if (BAMBOO_SEL_RMII(selection1_val)) + mode = PHY_MODE_RMII; + else + mode = PHY_MODE_SMII; + + /* Set mac_addr and phy mode for each EMAC */ + + def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0); + emacdata = def->additions; + memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6); + emacdata->phy_mode = mode; + + def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1); + emacdata = def->additions; + memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6); + emacdata->phy_mode = mode; +} + +static int +bamboo_exclude_device(unsigned char bus, unsigned char devfn) +{ + return (bus == 0 && devfn == 0); +} + +#define PCI_READW(offset) \ + (readw((void *)((u32)pci_reg_base+offset))) + +#define PCI_WRITEW(value, offset) \ + (writew(value, (void *)((u32)pci_reg_base+offset))) + +#define PCI_WRITEL(value, offset) \ + (writel(value, (void *)((u32)pci_reg_base+offset))) + +static void __init +bamboo_setup_pci(void) +{ + void *pci_reg_base; + unsigned long memory_size; + memory_size = ppc_md.find_end_of_memory(); + + pci_reg_base = ioremap64(BAMBOO_PCIL0_BASE, BAMBOO_PCIL0_SIZE); + + /* Enable PCI I/O, Mem, and Busmaster cycles */ + PCI_WRITEW(PCI_READW(PCI_COMMAND) | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER, PCI_COMMAND); + + /* Disable region first */ + PCI_WRITEL(0, BAMBOO_PCIL0_PMM0MA); + + /* PLB starting addr: 0x00000000A0000000 */ + PCI_WRITEL(BAMBOO_PCI_PHY_MEM_BASE, BAMBOO_PCIL0_PMM0LA); + + /* PCI start addr, 0xA0000000 (PCI Address) */ + PCI_WRITEL(BAMBOO_PCI_MEM_BASE, BAMBOO_PCIL0_PMM0PCILA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM0PCIHA); + + /* Enable no pre-fetch, enable region */ + PCI_WRITEL(((0xffffffff - + (BAMBOO_PCI_UPPER_MEM - BAMBOO_PCI_MEM_BASE)) | 0x01), + BAMBOO_PCIL0_PMM0MA); + + /* Disable region one */ + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1MA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1LA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1PCILA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1PCIHA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM1MA); + + /* Disable region two */ + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2MA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2LA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2PCILA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2PCIHA); + PCI_WRITEL(0, BAMBOO_PCIL0_PMM2MA); + + /* Now configure the PCI->PLB windows, we only use PTM1 + * + * For Inbound flow, set the window size to all available memory + * This is required because if size is smaller, + * then Eth/PCI DD would fail as PCI card not able to access + * the memory allocated by DD. + */ + + PCI_WRITEL(0, BAMBOO_PCIL0_PTM1MS); /* disabled region 1 */ + PCI_WRITEL(0, BAMBOO_PCIL0_PTM1LA); /* begin of address map */ + + memory_size = 1 << fls(memory_size - 1); + + /* Size low + Enabled */ + PCI_WRITEL((0xffffffff - (memory_size - 1)) | 0x1, BAMBOO_PCIL0_PTM1MS); + + eieio(); + iounmap(pci_reg_base); +} + +static void __init +bamboo_setup_hose(void) +{ + unsigned int bar_response, bar; + struct pci_controller *hose; + + bamboo_setup_pci(); + + hose = pcibios_alloc_controller(); + + if (!hose) + return; + + hose->first_busno = 0; + hose->last_busno = 0xff; + + hose->pci_mem_offset = BAMBOO_PCI_MEM_OFFSET; + + pci_init_resource(&hose->io_resource, + BAMBOO_PCI_LOWER_IO, + BAMBOO_PCI_UPPER_IO, + IORESOURCE_IO, + "PCI host bridge"); + + pci_init_resource(&hose->mem_resources[0], + BAMBOO_PCI_LOWER_MEM, + BAMBOO_PCI_UPPER_MEM, + IORESOURCE_MEM, + "PCI host bridge"); + + ppc_md.pci_exclude_device = bamboo_exclude_device; + + hose->io_space.start = BAMBOO_PCI_LOWER_IO; + hose->io_space.end = BAMBOO_PCI_UPPER_IO; + hose->mem_space.start = BAMBOO_PCI_LOWER_MEM; + hose->mem_space.end = BAMBOO_PCI_UPPER_MEM; + isa_io_base = + (unsigned long)ioremap64(BAMBOO_PCI_IO_BASE, BAMBOO_PCI_IO_SIZE); + hose->io_base_virt = (void *)isa_io_base; + + setup_indirect_pci(hose, + BAMBOO_PCI_CFGA_PLB32, + BAMBOO_PCI_CFGD_PLB32); + hose->set_cfg_type = 1; + + /* Zero config bars */ + for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { + early_write_config_dword(hose, hose->first_busno, + PCI_FUNC(hose->first_busno), bar, + 0x00000000); + early_read_config_dword(hose, hose->first_busno, + PCI_FUNC(hose->first_busno), bar, + &bar_response); + } + + hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = bamboo_map_irq; +} + +TODC_ALLOC(); + +static void __init +bamboo_early_serial_map(void) +{ + struct uart_port port; + + /* Setup ioremapped serial port access */ + memset(&port, 0, sizeof(port)); + port.membase = ioremap64(PPC440EP_UART0_ADDR, 8); + port.irq = 0; + port.uartclk = clocks.uart0; + port.regshift = 0; + port.iotype = SERIAL_IO_MEM; + port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + port.line = 0; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 0 failed\n"); + } + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(0, &port); +#endif + + port.membase = ioremap64(PPC440EP_UART1_ADDR, 8); + port.irq = 1; + port.uartclk = clocks.uart1; + port.line = 1; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 1 failed\n"); + } + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(1, &port); +#endif + + port.membase = ioremap64(PPC440EP_UART2_ADDR, 8); + port.irq = 3; + port.uartclk = clocks.uart2; + port.line = 2; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 2 failed\n"); + } + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + /* Configure debug serial access */ + gen550_init(2, &port); +#endif + + port.membase = ioremap64(PPC440EP_UART3_ADDR, 8); + port.irq = 4; + port.uartclk = clocks.uart3; + port.line = 3; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 3 failed\n"); + } +} + +static void __init +bamboo_setup_arch(void) +{ + + bamboo_set_emacdata(); + + ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); + ocp_sys_info.opb_bus_freq = clocks.opb; + + /* Setup TODC access */ + TODC_INIT(TODC_TYPE_DS1743, + 0, + 0, + ioremap64(BAMBOO_RTC_ADDR, BAMBOO_RTC_SIZE), + 8); + + /* init to some ~sane value until calibrate_delay() runs */ + loops_per_jiffy = 50000000/HZ; + + /* Setup PCI host bridge */ + bamboo_setup_hose(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + + bamboo_early_serial_map(); + + /* Identify the system */ + printk("IBM Bamboo port (MontaVista Software, Inc. (source@mvista.com))\n"); +} + +void __init platform_init(unsigned long r3, unsigned long r4, + unsigned long r5, unsigned long r6, unsigned long r7) +{ + parse_bootinfo(find_bootinfo()); + + /* + * If we were passed in a board information, copy it into the + * residual data area. + */ + if (r3) + __res = *(bd_t *)(r3 + KERNELBASE); + + + ibm44x_platform_init(); + + ppc_md.setup_arch = bamboo_setup_arch; + ppc_md.show_cpuinfo = bamboo_show_cpuinfo; + ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ + + ppc_md.calibrate_decr = bamboo_calibrate_decr; + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + + ppc_md.nvram_read_val = todc_direct_read_val; + ppc_md.nvram_write_val = todc_direct_write_val; +#ifdef CONFIG_KGDB + ppc_md.early_serial_map = bamboo_early_serial_map; +#endif +} + diff --git a/arch/ppc/platforms/4xx/bamboo.h b/arch/ppc/platforms/4xx/bamboo.h new file mode 100644 index 000000000000..63d714504148 --- /dev/null +++ b/arch/ppc/platforms/4xx/bamboo.h @@ -0,0 +1,136 @@ +/* + * arch/ppc/platforms/bamboo.h + * + * Bamboo board definitions + * + * Wade Farnsworth + * + * Copyright 2004 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef __ASM_BAMBOO_H__ +#define __ASM_BAMBOO_H__ + +#include +#include + +/* F/W TLB mapping used in bootloader glue to reset EMAC */ +#define PPC44x_EMAC0_MR0 0x0EF600E00 + +/* Location of MAC addresses in PIBS image */ +#define PIBS_FLASH_BASE 0xfff00000 +#define PIBS_MAC_BASE (PIBS_FLASH_BASE+0xc0400) +#define PIBS_MAC_SIZE 0x200 +#define PIBS_MAC_OFFSET 0x100 + +/* Default clock rate */ +#define BAMBOO_TMRCLK 25000000 + +/* RTC/NVRAM location */ +#define BAMBOO_RTC_ADDR 0x080000000ULL +#define BAMBOO_RTC_SIZE 0x2000 + +/* FPGA Registers */ +#define BAMBOO_FPGA_ADDR 0x080002000ULL + +#define BAMBOO_FPGA_CONFIG2_REG_ADDR (BAMBOO_FPGA_ADDR + 0x1) +#define BAMBOO_FULL_DUPLEX_EN(x) (x & 0x08) +#define BAMBOO_FORCE_100Mbps(x) (x & 0x04) +#define BAMBOO_AUTONEGOTIATE(x) (x & 0x02) + +#define BAMBOO_FPGA_SETTING_REG_ADDR (BAMBOO_FPGA_ADDR + 0x3) +#define BAMBOO_BOOT_SMALL_FLASH(x) (!(x & 0x80)) +#define BAMBOO_LARGE_FLASH_EN(x) (!(x & 0x40)) +#define BAMBOO_BOOT_NAND_FLASH(x) (!(x & 0x20)) + +#define BAMBOO_FPGA_SELECTION1_REG_ADDR (BAMBOO_FPGA_ADDR + 0x4) +#define BAMBOO_SEL_MII(x) (x & 0x80) +#define BAMBOO_SEL_RMII(x) (x & 0x40) +#define BAMBOO_SEL_SMII(x) (x & 0x20) + +/* Flash */ +#define BAMBOO_SMALL_FLASH_LOW 0x087f00000ULL +#define BAMBOO_SMALL_FLASH_HIGH 0x0fff00000ULL +#define BAMBOO_SMALL_FLASH_SIZE 0x100000 +#define BAMBOO_LARGE_FLASH_LOW 0x087800000ULL +#define BAMBOO_LARGE_FLASH_HIGH1 0x0ff800000ULL +#define BAMBOO_LARGE_FLASH_HIGH2 0x0ffc00000ULL +#define BAMBOO_LARGE_FLASH_SIZE 0x400000 +#define BAMBOO_SRAM_LOW 0x087f00000ULL +#define BAMBOO_SRAM_HIGH1 0x0fff00000ULL +#define BAMBOO_SRAM_HIGH2 0x0ff800000ULL +#define BAMBOO_SRAM_SIZE 0x100000 +#define BAMBOO_NAND_FLASH_REG_ADDR 0x090000000ULL +#define BAMBOO_NAND_FLASH_REG_SIZE 0x2000 + +/* + * Serial port defines + */ +#define RS_TABLE_SIZE 4 + +#define UART0_IO_BASE 0xEF600300 +#define UART1_IO_BASE 0xEF600400 +#define UART2_IO_BASE 0xEF600500 +#define UART3_IO_BASE 0xEF600600 + +#define BASE_BAUD 33177600/3/16 +#define UART0_INT 0 +#define UART1_INT 1 +#define UART2_INT 3 +#define UART3_INT 4 + +#define STD_UART_OP(num) \ + { 0, BASE_BAUD, 0, UART##num##_INT, \ + (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ + iomem_base: UART##num##_IO_BASE, \ + io_type: SERIAL_IO_MEM}, + +#define SERIAL_PORT_DFNS \ + STD_UART_OP(0) \ + STD_UART_OP(1) \ + STD_UART_OP(2) \ + STD_UART_OP(3) + +/* PCI support */ +#define BAMBOO_PCI_CFGA_PLB32 0xeec00000 +#define BAMBOO_PCI_CFGD_PLB32 0xeec00004 + +#define BAMBOO_PCI_IO_BASE 0x00000000e8000000ULL +#define BAMBOO_PCI_IO_SIZE 0x00010000 +#define BAMBOO_PCI_MEM_OFFSET 0x00000000 +#define BAMBOO_PCI_PHY_MEM_BASE 0x00000000a0000000ULL + +#define BAMBOO_PCI_LOWER_IO 0x00000000 +#define BAMBOO_PCI_UPPER_IO 0x0000ffff +#define BAMBOO_PCI_LOWER_MEM 0xa0000000 +#define BAMBOO_PCI_UPPER_MEM 0xafffffff +#define BAMBOO_PCI_MEM_BASE 0xa0000000 + +#define BAMBOO_PCIL0_BASE 0x00000000ef400000ULL +#define BAMBOO_PCIL0_SIZE 0x40 + +#define BAMBOO_PCIL0_PMM0LA 0x000 +#define BAMBOO_PCIL0_PMM0MA 0x004 +#define BAMBOO_PCIL0_PMM0PCILA 0x008 +#define BAMBOO_PCIL0_PMM0PCIHA 0x00C +#define BAMBOO_PCIL0_PMM1LA 0x010 +#define BAMBOO_PCIL0_PMM1MA 0x014 +#define BAMBOO_PCIL0_PMM1PCILA 0x018 +#define BAMBOO_PCIL0_PMM1PCIHA 0x01C +#define BAMBOO_PCIL0_PMM2LA 0x020 +#define BAMBOO_PCIL0_PMM2MA 0x024 +#define BAMBOO_PCIL0_PMM2PCILA 0x028 +#define BAMBOO_PCIL0_PMM2PCIHA 0x02C +#define BAMBOO_PCIL0_PTM1MS 0x030 +#define BAMBOO_PCIL0_PTM1LA 0x034 +#define BAMBOO_PCIL0_PTM2MS 0x038 +#define BAMBOO_PCIL0_PTM2LA 0x03C + +#endif /* __ASM_BAMBOO_H__ */ +#endif /* __KERNEL__ */ -- cgit v1.2.3 From 61d44c777a02245a5032a2ca77a12f915416572d Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Sun, 31 Jul 2005 22:34:53 -0700 Subject: [PATCH] ppc32: add bamboo defconfig Add Bamboo platform defconfig Signed-off-by: Wade Farnsworth Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/configs/bamboo_defconfig | 943 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 943 insertions(+) create mode 100644 arch/ppc/configs/bamboo_defconfig diff --git a/arch/ppc/configs/bamboo_defconfig b/arch/ppc/configs/bamboo_defconfig new file mode 100644 index 000000000000..0ba4e70d50b6 --- /dev/null +++ b/arch/ppc/configs/bamboo_defconfig @@ -0,0 +1,943 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.12 +# Tue Jun 28 15:24:25 2005 +# +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Processor +# +# CONFIG_6xx is not set +# CONFIG_40x is not set +CONFIG_44x=y +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +# CONFIG_E500 is not set +CONFIG_PPC_FPU=y +CONFIG_BOOKE=y +CONFIG_PTE_64BIT=y +CONFIG_PHYS_64BIT=y +# CONFIG_MATH_EMULATION is not set +# CONFIG_KEXEC is not set +# CONFIG_CPU_FREQ is not set +CONFIG_4xx=y + +# +# IBM 4xx options +# +CONFIG_BAMBOO=y +# CONFIG_EBONY is not set +# CONFIG_LUAN is not set +# CONFIG_OCOTEA is not set +CONFIG_440EP=y +CONFIG_440=y +CONFIG_IBM440EP_ERR42=y +CONFIG_IBM_OCP=y +# CONFIG_PPC4xx_DMA is not set +CONFIG_PPC_GEN550=y +# CONFIG_PM is not set +CONFIG_NOT_COHERENT_CACHE=y + +# +# Platform options +# +# CONFIG_PC_KEYBOARD is not set +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="ip=on" +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_CONSISTENT_START=0xff100000 +CONFIG_CONSISTENT_SIZE=0x00200000 +CONFIG_BOOT_LOAD=0x01000000 + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_LBD is not set +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +# CONFIG_BLK_DEV_SD is not set +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_IBM_EMAC=y +# CONFIG_IBM_EMAC_ERRMSG is not set +CONFIG_IBM_EMAC_RXB=64 +CONFIG_IBM_EMAC_TXB=8 +CONFIG_IBM_EMAC_FGAP=8 +CONFIG_IBM_EMAC_SKBRES=0 +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +CONFIG_EEPRO100=y +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +CONFIG_NATSEMI=y +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SKGE is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=y +CONFIG_USB_DEBUG=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# +# CONFIG_USB_STORAGE is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +CONFIG_USB_PEGASUS=y +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set + +# +# XFS support +# +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +# CONFIG_DEVPTS_FS_XATTR is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_KGDB is not set +# CONFIG_XMON is not set +CONFIG_BDI_SWITCH=y +# CONFIG_SERIAL_TEXT_DEBUG is not set +CONFIG_PPC_OCP=y + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# -- cgit v1.2.3 From 4374ae10e5ef577d8fd73fdadcdb37149d8b3953 Mon Sep 17 00:00:00 2001 From: Eugene Surovegin Date: Sun, 31 Jul 2005 22:34:54 -0700 Subject: [PATCH] ppc32: add missing 4xx EMAC sysfs nodes Add missing 4xx EMAC data sysfs nodes. Signed-off-by: Eugene Surovegin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-ppc/ibm_ocp.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/include/asm-ppc/ibm_ocp.h b/include/asm-ppc/ibm_ocp.h index 8c61d93043af..3f7b5669e6d5 100644 --- a/include/asm-ppc/ibm_ocp.h +++ b/include/asm-ppc/ibm_ocp.h @@ -71,6 +71,8 @@ struct ocp_func_emac_data { /* Sysfs support */ #define OCP_SYSFS_EMAC_DATA() \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, rgmii_idx) \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, rgmii_mux) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, zmii_idx) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, zmii_mux) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_idx) \ @@ -78,9 +80,14 @@ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_rx_chan) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mal_tx_chan) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, wol_irq) \ OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, mdio_idx) \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, tah_idx) \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "%d\n", emac, phy_mode) \ +OCP_SYSFS_ADDTL(struct ocp_func_emac_data, "0x%08x\n", emac, phy_map) \ \ void ocp_show_emac_data(struct device *dev) \ { \ + device_create_file(dev, &dev_attr_emac_rgmii_idx); \ + device_create_file(dev, &dev_attr_emac_rgmii_mux); \ device_create_file(dev, &dev_attr_emac_zmii_idx); \ device_create_file(dev, &dev_attr_emac_zmii_mux); \ device_create_file(dev, &dev_attr_emac_mal_idx); \ @@ -88,6 +95,9 @@ void ocp_show_emac_data(struct device *dev) \ device_create_file(dev, &dev_attr_emac_mal_tx_chan); \ device_create_file(dev, &dev_attr_emac_wol_irq); \ device_create_file(dev, &dev_attr_emac_mdio_idx); \ + device_create_file(dev, &dev_attr_emac_tah_idx); \ + device_create_file(dev, &dev_attr_emac_phy_mode); \ + device_create_file(dev, &dev_attr_emac_phy_map); \ } #ifdef CONFIG_40x @@ -157,7 +167,7 @@ OCP_SYSFS_ADDTL(struct ocp_func_iic_data, "%d\n", iic, fast_mode) \ \ void ocp_show_iic_data(struct device *dev) \ { \ - device_create_file(dev, &dev_attr_iic_fast_mode); \ + device_create_file(dev, &dev_attr_iic_fast_mode); \ } #endif /* __IBM_OCP_H__ */ #endif /* __KERNEL__ */ -- cgit v1.2.3 From 5d3f229fcd4409d3e182b204defc122eb7833535 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 1 Aug 2005 21:11:33 -0700 Subject: [PATCH] s390: kexec fixes and improvements. Disable pseudo page fault handling before starting the new kernel and try to use diag308 to reset the machine. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/machine_kexec.c | 7 ++++++ arch/s390/kernel/relocate_kernel.S | 41 +++++++++++++++++++++++++++++++- arch/s390/kernel/relocate_kernel64.S | 45 ++++++++++++++++++++++++++++++++++-- arch/s390/kernel/smp.c | 6 +++-- arch/s390/kernel/traps.c | 15 ++++++++++++ 5 files changed, 109 insertions(+), 5 deletions(-) diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 2721c3a32b84..5aa71b05b8ae 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -70,6 +70,8 @@ machine_kexec(struct kimage *image) for (;;); } +extern void pfault_fini(void); + static void kexec_halt_all_cpus(void *kernel_image) { @@ -78,6 +80,11 @@ kexec_halt_all_cpus(void *kernel_image) struct kimage *image; relocate_kernel_t data_mover; +#ifdef CONFIG_PFAULT + if (MACHINE_IS_VM) + pfault_fini(); +#endif + if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid)) signal_processor(smp_processor_id(), sigp_stop); diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S index d5e4a62fbb79..2a25ec7147ff 100644 --- a/arch/s390/kernel/relocate_kernel.S +++ b/arch/s390/kernel/relocate_kernel.S @@ -4,6 +4,7 @@ * (C) Copyright IBM Corp. 2005 * * Author(s): Rolf Adelsberger + * Heiko Carstens * */ @@ -25,8 +26,31 @@ relocate_kernel: basr %r13,0 #base address .base: - spx zero64-.base(%r13) #absolute addressing mode stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQ (external) + spx zero64-.base(%r13) #absolute addressing mode + stctl %c0,%c15,ctlregs-.base(%r13) + stm %r0,%r15,gprregs-.base(%r13) + la %r1,load_psw-.base(%r13) + mvc 0(8,%r0),0(%r1) + la %r0,.back-.base(%r13) + st %r0,4(%r0) + oi 4(%r0),0x80 + mvc 0x68(8,%r0),0(%r1) + la %r0,.back_pgm-.base(%r13) + st %r0,0x6c(%r0) + oi 0x6c(%r0),0x80 + lhi %r0,0 + diag %r0,%r0,0x308 + .back: + basr %r13,0 + .back_base: + oi have_diag308-.back_base(%r13),0x01 + lctl %c0,%c15,ctlregs-.back_base(%r13) + lm %r0,%r15,gprregs-.back_base(%r13) + j .start_reloc + .back_pgm: + lm %r0,%r15,gprregs-.base(%r13) + .start_reloc: lhi %r10,-1 #preparing the mask sll %r10,12 #shift it such that it becomes 0xf000 .top: @@ -63,6 +87,10 @@ o %r3,4(%r4) #or load address into psw st %r3,4(%r4) mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0 + tm have_diag308-.base(%r13),0x01 + jno .no_diag308 + diag %r0,%r0,0x308 + .no_diag308: sr %r1,%r1 #clear %r1 sr %r2,%r2 #clear %r2 sigp %r1,%r2,0x12 #set cpuid to zero @@ -75,6 +103,17 @@ .long 0x00080000,0x80000000 sys_msk: .quad 0 + ctlregs: + .rept 16 + .long 0 + .endr + gprregs: + .rept 16 + .long 0 + .endr + have_diag308: + .byte 0 + .align 8 relocate_kernel_end: .globl relocate_kernel_len relocate_kernel_len: diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S index 96290cc4eb3c..8cdb86e8911f 100644 --- a/arch/s390/kernel/relocate_kernel64.S +++ b/arch/s390/kernel/relocate_kernel64.S @@ -4,6 +4,7 @@ * (C) Copyright IBM Corp. 2005 * * Author(s): Rolf Adelsberger + * Heiko Carstens * */ @@ -26,8 +27,34 @@ relocate_kernel: basr %r13,0 #base address .base: + stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQs spx zero64-.base(%r13) #absolute addressing mode - stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQ (external) + stctg %c0,%c15,ctlregs-.base(%r13) + stmg %r0,%r15,gprregs-.base(%r13) + lghi %r0,3 + sllg %r0,%r0,31 + stg %r0,0x1d0(%r0) + la %r0,.back_pgm-.base(%r13) + stg %r0,0x1d8(%r0) + la %r1,load_psw-.base(%r13) + mvc 0(8,%r0),0(%r1) + la %r0,.back-.base(%r13) + st %r0,4(%r0) + oi 4(%r0),0x80 + lghi %r0,0 + diag %r0,%r0,0x308 + .back: + lhi %r1,1 #mode 1 = esame + sigp %r1,%r0,0x12 #switch to esame mode + sam64 #switch to 64 bit addressing mode + basr %r13,0 + .back_base: + oi have_diag308-.back_base(%r13),0x01 + lctlg %c0,%c15,ctlregs-.back_base(%r13) + lmg %r0,%r15,gprregs-.back_base(%r13) + j .top + .back_pgm: + lmg %r0,%r15,gprregs-.base(%r13) .top: lghi %r7,4096 #load PAGE_SIZE in r7 lghi %r9,4096 #load PAGE_SIZE in r9 @@ -62,6 +89,10 @@ o %r3,4(%r4) #or load address into psw st %r3,4(%r4) mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0 + tm have_diag308-.base(%r13),0x01 + jno .no_diag308 + diag %r0,%r0,0x308 + .no_diag308: sam31 #31 bit mode sr %r1,%r1 #erase register r1 sr %r2,%r2 #erase register r2 @@ -75,8 +106,18 @@ .long 0x00080000,0x80000000 sys_msk: .quad 0 + ctlregs: + .rept 16 + .quad 0 + .endr + gprregs: + .rept 16 + .quad 0 + .endr + have_diag308: + .byte 0 + .align 8 relocate_kernel_end: .globl relocate_kernel_len relocate_kernel_len: .quad relocate_kernel_end - relocate_kernel - diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index da77f001af8d..85222fee4361 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -537,7 +537,8 @@ int __devinit start_secondary(void *cpuvoid) #endif #ifdef CONFIG_PFAULT /* Enable pfault pseudo page faults on this cpu. */ - pfault_init(); + if (MACHINE_IS_VM) + pfault_init(); #endif /* Mark this cpu as online */ cpu_set(smp_processor_id(), cpu_online_map); @@ -690,7 +691,8 @@ __cpu_disable(void) #ifdef CONFIG_PFAULT /* Disable pfault pseudo page faults on this cpu. */ - pfault_fini(); + if (MACHINE_IS_VM) + pfault_fini(); #endif /* disable all external interrupts */ diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index bc7b7be7acbe..6b8703ec2ae6 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -675,6 +676,19 @@ asmlinkage void kernel_stack_overflow(struct pt_regs * regs) panic("Corrupt kernel stack, can't continue."); } +#ifndef CONFIG_ARCH_S390X +static int +pagex_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + if (MACHINE_IS_VM) + cpcmd("SET PAGEX OFF", NULL, 0, NULL); + return NOTIFY_DONE; +} + +static struct notifier_block pagex_reboot_notifier = { + .notifier_call = &pagex_reboot_event, +}; +#endif /* init is done in lowcore.S and head.S */ @@ -735,6 +749,7 @@ void __init trap_init(void) &ext_int_pfault); #endif #ifndef CONFIG_ARCH_S390X + register_reboot_notifier(&pagex_reboot_notifier); cpcmd("SET PAGEX ON", NULL, 0, NULL); #endif } -- cgit v1.2.3 From d2013485a52fb7ece48e5688b443cc098f4dbbdf Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 1 Aug 2005 21:11:34 -0700 Subject: [PATCH] s390: ioprio & inotify system calls. Add system calls for io priorities and inotify. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/compat_wrapper.S | 26 ++++++++++++++++++++++++++ arch/s390/kernel/syscalls.S | 5 +++++ include/asm-s390/unistd.h | 7 ++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 799a98eac92d..23fe94e58688 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1449,3 +1449,29 @@ compat_sys_kexec_load_wrapper: llgtr %r4,%r4 # struct kexec_segment * llgfr %r5,%r5 # unsigned long jg compat_sys_kexec_load + + .globl sys_ioprio_set_wrapper +sys_ioprio_set_wrapper: + lgfr %r2,%r2 # int + lgfr %r3,%r3 # int + lgfr %r4,%r4 # int + jg sys_ioprio_set + + .globl sys_ioprio_get_wrapper +sys_ioprio_get_wrapper: + lgfr %r2,%r2 # int + lgfr %r3,%r3 # int + jg sys_ioprio_get + + .globl sys_inotify_add_watch_wrapper +sys_inotify_add_watch_wrapper: + lgfr %r2,%r2 # int + llgtr %r3,%r3 # const char * + llgfr %r4,%r4 # u32 + jg sys_inotify_add_watch + + .globl sys_inotify_rm_watch_wrapper +sys_inotify_rm_watch_wrapper: + lgfr %r2,%r2 # int + llgfr %r3,%r3 # u32 + jg sys_inotify_rm_watch diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index a8668afb5f87..426d7cafdab3 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -290,3 +290,8 @@ SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper) SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper) SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl) /* 280 */ SYSCALL(sys_waitid,sys_waitid,compat_sys_waitid_wrapper) +SYSCALL(sys_ioprio_set,sys_ioprio_set,sys_ioprio_set_wrapper) +SYSCALL(sys_ioprio_get,sys_ioprio_get,sys_ioprio_get_wrapper) +SYSCALL(sys_inotify_init,sys_inotify_init,sys_inotify_init) +SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper) +SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,sys_inotify_rm_watch_wrapper) diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h index 363db45f8d07..221e965da924 100644 --- a/include/asm-s390/unistd.h +++ b/include/asm-s390/unistd.h @@ -274,8 +274,13 @@ #define __NR_request_key 279 #define __NR_keyctl 280 #define __NR_waitid 281 +#define __NR_ioprio_set 282 +#define __NR_ioprio_get 283 +#define __NR_inotify_init 284 +#define __NR_inotify_add_watch 285 +#define __NR_inotify_rm_watch 286 -#define NR_syscalls 282 +#define NR_syscalls 287 /* * There are some system calls that are not present on 64 bit, some -- cgit v1.2.3 From 2757a71c3122c7653e3dd8077ad6ca71efb1d450 Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Mon, 1 Aug 2005 21:11:35 -0700 Subject: [PATCH] m32r: Fix local-timer event handling There was a scheduling problem of the m32r SMP kernel; A process rarely stopped and gave no responding but the other process have been handled by the other CPU still lives, then if we did something in the other terminal or something like that, the stopped process came back to life and continued its operation... (ex. LMbench: lat_sig) In the m32r SMP kernel, a local-timer event is delivered by using an IPI(inter processor interrupts); LOCAL_TIMER_IPI. And a function smp_send_timer() is prepared to send the LOCAL_TIMER_IPI from the current CPU to the other CPUs. The funtion smp_send_timer() was placed and used in do_IRQ() in former times (before 2.6.10-rc3-mm1 kernel), however, it was unintentionally removed when arch/m32r/kernel/irq.c was modified to employ the generic hardirq framework (CONFIG_GENERIC_HARDIRQ) in my previous patch. [PATCH 2.6.10-rc3-mm1] m32r: Use generic hardirq framework http://www.ussg.iu.edu/hypermail/linux/kernel/0412.2/0358.html The following patch fixes the above problem. Signed-off-by: Hitoshi Yamamoto Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m32r/kernel/time.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index 3c4707280a52..8a2b77bc5749 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -205,8 +205,7 @@ static long last_rtc_update = 0; * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -static inline void -do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { #ifndef CONFIG_SMP profile_tick(CPU_PROFILING, regs); @@ -221,6 +220,7 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. */ + write_seqlock(&xtime_lock); if ((time_status & STA_UNSYNC) == 0 && xtime.tv_sec > last_rtc_update + 660 && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2 @@ -231,6 +231,7 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) else /* do it again in 60 s */ last_rtc_update = xtime.tv_sec - 600; } + write_sequnlock(&xtime_lock); /* As we return to user mode fire off the other CPU schedulers.. this is basically because we don't yet share IRQ's around. This message is rigged to be safe on the 386 - basically it's @@ -238,14 +239,8 @@ do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) #ifdef CONFIG_SMP smp_local_timer_interrupt(regs); + smp_send_timer(); #endif -} - -irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - write_seqlock(&xtime_lock); - do_timer_interrupt(irq, NULL, regs); - write_sequnlock(&xtime_lock); return IRQ_HANDLED; } -- cgit v1.2.3 From 43f2f3d343f9d00a94a9242547a59d9dfb2338c4 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Mon, 1 Aug 2005 21:11:37 -0700 Subject: [PATCH] aacraid: Fix for controller load based timeouts Martin Drab found that he could get aacraid timeouts with high load on his controller / disk drive combinations. After some experimentation Mark Salyzyn has come up with a patch to reduce the default max_sectors to something that will keep the controller from being overloaded and will eliminate the timeout issues. Signed-off-by: Mark Haverkamp Cc: James Bottomley Acked-by: Mark Salyzyn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/aacraid/aacraid.h | 6 +----- drivers/scsi/aacraid/linit.c | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 3a11a536c0da..4ab07861b457 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -15,11 +15,7 @@ #define AAC_MAX_LUN (8) #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) -/* - * max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512 - * Linux has starvation problems if we permit larger than 4MB I/O ... - */ -#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)8192) +#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)512) /* * These macros convert from physical channels to virtual channels diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index c1a4f978fcba..562da90480a1 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -374,7 +374,8 @@ static int aac_slave_configure(struct scsi_device *sdev) else scsi_adjust_queue_depth(sdev, 0, 1); - if (host->max_sectors < AAC_MAX_32BIT_SGBCOUNT) + if (!(((struct aac_dev *)host->hostdata)->adapter_info.options + & AAC_OPT_NEW_COMM)) blk_queue_max_segment_size(sdev->request_queue, 65536); return 0; -- cgit v1.2.3 From 001abc93bf83f95737cd455b6ec875e6412f7d53 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 1 Aug 2005 21:11:38 -0700 Subject: [PATCH] v4l: bug fix to correct tea5767 autodetection This patch does correct radio chip autodetection to avoid misdetecting mt20xx microtune as tea5767 chip. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/tea5767.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index c8fd4204cd0a..cebcc1fa68d1 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -2,7 +2,7 @@ * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview * I2C address is allways 0xC0. * - * $Id: tea5767.c,v 1.26 2005/07/27 12:00:36 mkrufky Exp $ + * $Id: tea5767.c,v 1.27 2005/07/31 12:10:56 mchehab Exp $ * * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) * This code is placed under the terms of the GNU General Public License @@ -296,7 +296,7 @@ int tea5767_autodetection(struct i2c_client *c) int rc; struct tuner *t = i2c_get_clientdata(c); - if (5 != (rc = i2c_master_recv(c, buffer, 5))) { + if (7 != (rc = i2c_master_recv(c, buffer, 7))) { tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc); return EINVAL; } @@ -323,6 +323,12 @@ int tea5767_autodetection(struct i2c_client *c) return EINVAL; } + /* It seems that tea5767 returns 0xff after the 5th byte */ + if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) { + tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n"); + return EINVAL; + } + tuner_warn("TEA5767 detected.\n"); return 0; } @@ -331,7 +337,8 @@ int tea5767_tuner_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio"); + tuner_info("type set to %d (%s)\n", t->type, + "Philips TEA5767HN FM Radio"); strlcpy(c->name, "tea5767", sizeof(c->name)); t->tv_freq = set_tv_freq; -- cgit v1.2.3 From 0072b1389c25355ccc01048114adb9652c13fd9f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 1 Aug 2005 21:11:39 -0700 Subject: [PATCH] include/linux/dcookies.h: dummy functions must be "static inline" We don't want these to be global functions. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/dcookies.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/dcookies.h b/include/linux/dcookies.h index c28050136164..1d68428c925d 100644 --- a/include/linux/dcookies.h +++ b/include/linux/dcookies.h @@ -48,12 +48,12 @@ int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt, #else -struct dcookie_user * dcookie_register(void) +static inline struct dcookie_user * dcookie_register(void) { return NULL; } -void dcookie_unregister(struct dcookie_user * user) +static inline void dcookie_unregister(struct dcookie_user * user) { return; } -- cgit v1.2.3 From f76d28d235cf777dd2e1c1d48c16ee10c1d1587f Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Mon, 1 Aug 2005 21:11:40 -0700 Subject: [PATCH] hfs: don't dirty unchanged inode If inode size hasn't changed, don't do anything further in truncate, which also prevents a dirty inode, what might upset some readonly devices quite badly. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hfs/extent.c | 3 ++- fs/hfsplus/extents.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c index cbc8510ad222..5ea6b3d45eaa 100644 --- a/fs/hfs/extent.c +++ b/fs/hfs/extent.c @@ -482,7 +482,8 @@ void hfs_file_truncate(struct inode *inode) page_cache_release(page); mark_inode_dirty(inode); return; - } + } else if (inode->i_size == HFS_I(inode)->phys_size) + return; size = inode->i_size + HFS_SB(sb)->alloc_blksz - 1; blk_cnt = size / HFS_SB(sb)->alloc_blksz; alloc_cnt = HFS_I(inode)->alloc_blocks; diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 376498cc64fd..e7235ca79a95 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -461,7 +461,9 @@ void hfsplus_file_truncate(struct inode *inode) page_cache_release(page); mark_inode_dirty(inode); return; - } + } else if (inode->i_size == HFSPLUS_I(inode).phys_size) + return; + blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift; alloc_cnt = HFSPLUS_I(inode).alloc_blocks; if (blk_cnt == alloc_cnt) -- cgit v1.2.3 From 74f9c9c258249fba3e2e78f70691528426a6c010 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Mon, 1 Aug 2005 21:11:41 -0700 Subject: [PATCH] hfs: don't reference missing page If there was a read error, the bnode might miss some pages, so skip them. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hfs/bnode.c | 2 ++ fs/hfsplus/bnode.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c index 6ad1211f84ed..a096c5a56664 100644 --- a/fs/hfs/bnode.c +++ b/fs/hfs/bnode.c @@ -480,6 +480,8 @@ void hfs_bnode_put(struct hfs_bnode *node) return; } for (i = 0; i < tree->pages_per_bnode; i++) { + if (!node->page[i]) + continue; mark_page_accessed(node->page[i]); #if REF_PAGES put_page(node->page[i]); diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index 267872e84d71..8868d3b766fd 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -643,6 +643,8 @@ void hfs_bnode_put(struct hfs_bnode *node) return; } for (i = 0; i < tree->pages_per_bnode; i++) { + if (!node->page[i]) + continue; mark_page_accessed(node->page[i]); #if REF_PAGES put_page(node->page[i]); -- cgit v1.2.3 From 690dbe1ced143876d8fa56b72310738dbe079d0a Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 1 Aug 2005 21:11:42 -0700 Subject: [PATCH] x86_64: access of some bad address x86_64 has a large sparse gate area between VSYSCALL_START and VSYSCALL_END, not all of it presently backed by pmds. Alexander Nyberg has found that in some circumstances gdb may try to ptrace here, and hit get_user_pages BUG_ON. It seems odd that gdb should be accessing here, but it certainly shouldn't crash in this way: relax BUG_ON to -EFAULT. Fixes kernel bugzilla #4801. Signed-off-by: Hugh Dickins Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 4e1c673784db..2405289dfdf8 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -910,9 +910,13 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, pud = pud_offset(pgd, pg); BUG_ON(pud_none(*pud)); pmd = pmd_offset(pud, pg); - BUG_ON(pmd_none(*pmd)); + if (pmd_none(*pmd)) + return i ? : -EFAULT; pte = pte_offset_map(pmd, pg); - BUG_ON(pte_none(*pte)); + if (pte_none(*pte)) { + pte_unmap(pte); + return i ? : -EFAULT; + } if (pages) { pages[i] = pte_page(*pte); get_page(pages[i]); -- cgit v1.2.3 From ba17101b41977f124948e0a7797fdcbb59e19f3e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 1 Aug 2005 21:11:43 -0700 Subject: [PATCH] sys_set_mempolicy() doesnt check if mode < 0 A kernel BUG() is triggered by a call to set_mempolicy() with a negative first argument. This is because the mode is declared as an int, and the validity check doesnt check < 0 values. Alternatively, mode could be declared as unsigned int or unsigned long. Signed-off-by: Eric Dumazet Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mempolicy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 1694845526be..b4eababc8198 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -443,7 +443,7 @@ asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask, struct mempolicy *new; DECLARE_BITMAP(nodes, MAX_NUMNODES); - if (mode > MPOL_MAX) + if (mode < 0 || mode > MPOL_MAX) return -EINVAL; err = get_nodes(nodes, nmask, maxnode, mode); if (err) -- cgit v1.2.3 From 39bbb07d7c0cf3e374831d1474e2246d9cabd931 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 1 Aug 2005 21:11:44 -0700 Subject: [PATCH] transmeta: CONFIG_PROC_FS=n build fix Fix bug found by Grant Coady 's autobuild setup. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/transmeta.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c index d8e59e198675..fc426380366b 100644 --- a/arch/i386/kernel/cpu/transmeta.c +++ b/arch/i386/kernel/cpu/transmeta.c @@ -77,9 +77,11 @@ static void __init init_transmeta(struct cpuinfo_x86 *c) if ( c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686 ) c->x86 = 6; +#ifdef CONFIG_SYSCTL /* randomize_va_space slows us down enormously; it probably triggers retranslation of x86->native bytecode */ randomize_va_space = 0; +#endif } static void transmeta_identify(struct cpuinfo_x86 * c) -- cgit v1.2.3 From 6ade43fbbcc3c12f0ddba112351d14d6c82ae476 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 1 Aug 2005 21:11:45 -0700 Subject: [PATCH] shm: CONFIG_SHMEM=n build fix Fix bug found by Grant Coady 's autobuild setup. shmem_set_policy() and shmem_get_policy() are macros if !CONFIG_SHMEM, so this doesn't work. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/shm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipc/shm.c b/ipc/shm.c index cce022435dbc..1d6cf08d950b 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -170,7 +170,7 @@ static struct vm_operations_struct shm_vm_ops = { .open = shm_open, /* callback for a new vm-area open */ .close = shm_close, /* callback for when the vm-area is released */ .nopage = shmem_nopage, -#ifdef CONFIG_NUMA +#if defined(CONFIG_NUMA) && defined(CONFIG_SHMEM) .set_policy = shmem_set_policy, .get_policy = shmem_get_policy, #endif -- cgit v1.2.3 From 561fb765b97f287211a2c73a844c5edb12f44f1d Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 1 Aug 2005 21:11:46 -0700 Subject: [PATCH] ppc64: topology API fix Dont include asm-generic/topology.h unconditionally, we end up overriding all the ppc64 specific functions when NUMA is on. Signed-off-by: Anton Blanchard Acked-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-ppc64/topology.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h index fcdcfd26a26b..1e9b19073230 100644 --- a/include/asm-ppc64/topology.h +++ b/include/asm-ppc64/topology.h @@ -33,6 +33,7 @@ static inline int node_to_first_cpu(int node) return first_cpu(tmp); } +#define pcibus_to_node(node) (-1) #define pcibus_to_cpumask(bus) (cpu_online_map) #define nr_cpus_node(node) (nr_cpus_in_node[node]) @@ -59,8 +60,10 @@ static inline int node_to_first_cpu(int node) .nr_balance_failed = 0, \ } -#endif /* CONFIG_NUMA */ +#else #include +#endif /* CONFIG_NUMA */ + #endif /* _ASM_PPC64_TOPOLOGY_H */ -- cgit v1.2.3 From 842bbaaa7394820c8f1fe0629cd15478653caf86 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 1 Aug 2005 21:11:47 -0700 Subject: [PATCH] Module per-cpu alignment cannot always be met The module code assumes noone will ever ask for a per-cpu area more than SMP_CACHE_BYTES aligned. However, as these cases show, gcc asks sometimes asks for 32-byte alignment for the per-cpu section on a module, and if CONFIG_X86_L1_CACHE_SHIFT is 4, we hit that BUG_ON(). This is obviously an unusual combination, as there have been few reports, but better to warn than die. See: http://www.ussg.iu.edu/hypermail/linux/kernel/0409.0/0768.html And more recently: http://bugs.gentoo.org/show_bug.cgi?id=97006 Signed-off-by: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/module.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index 068e271ab3a5..c32995fbd8fd 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -250,13 +250,18 @@ static inline unsigned int block_size(int val) /* Created by linker magic */ extern char __per_cpu_start[], __per_cpu_end[]; -static void *percpu_modalloc(unsigned long size, unsigned long align) +static void *percpu_modalloc(unsigned long size, unsigned long align, + const char *name) { unsigned long extra; unsigned int i; void *ptr; - BUG_ON(align > SMP_CACHE_BYTES); + if (align > SMP_CACHE_BYTES) { + printk(KERN_WARNING "%s: per-cpu alignment %li > %i\n", + name, align, SMP_CACHE_BYTES); + align = SMP_CACHE_BYTES; + } ptr = __per_cpu_start; for (i = 0; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) { @@ -348,7 +353,8 @@ static int percpu_modinit(void) } __initcall(percpu_modinit); #else /* ... !CONFIG_SMP */ -static inline void *percpu_modalloc(unsigned long size, unsigned long align) +static inline void *percpu_modalloc(unsigned long size, unsigned long align, + const char *name) { return NULL; } @@ -1644,7 +1650,8 @@ static struct module *load_module(void __user *umod, if (pcpuindex) { /* We have a special allocation for this section. */ percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, - sechdrs[pcpuindex].sh_addralign); + sechdrs[pcpuindex].sh_addralign, + mod->name); if (!percpu) { err = -ENOMEM; goto free_mod; -- cgit v1.2.3 From 96cd5b0856a25e2ec366702e1923070ffca53dae Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Mon, 1 Aug 2005 21:11:48 -0700 Subject: [PATCH] ppc64: POWER 4 fails to boot with NUMA If CONFIG_NUMA is set, some POWER 4 systems will fail to boot. This is because of special processing needed to handle invalid node IDs (0xffff) on POWER 4. My previous patch to handle memory 'holes' within nodes forgot to add this special case for POWER 4 in one place. In reality, I'm not sure that configuring the kernel for NUMA on POWER 4 makes much sense. Are there POWER 4 based systems with NUMA characteristics that are presented by the firmware? But, distros want one kernel for all systems so NUMA is on by default in their kernels. The patch handles those cases. Signed-off-by: Mike Kravetz Signed-off-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/mm/numa.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c index cafd91aef289..0b191f2de016 100644 --- a/arch/ppc64/mm/numa.c +++ b/arch/ppc64/mm/numa.c @@ -647,7 +647,12 @@ void __init do_init_bootmem(void) new_range: mem_start = read_n_cells(addr_cells, &memcell_buf); mem_size = read_n_cells(size_cells, &memcell_buf); - numa_domain = numa_enabled ? of_node_numa_domain(memory) : 0; + if (numa_enabled) { + numa_domain = of_node_numa_domain(memory); + if (numa_domain >= MAX_NUMNODES) + numa_domain = 0; + } else + numa_domain = 0; if (numa_domain != nid) continue; -- cgit v1.2.3 From 9a351e30d72d409ec62c83f380e330e0baa584b4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 1 Aug 2005 21:45:48 -0700 Subject: Linux v2.6.13-rc5 Ok, let's get it right this time --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 717b9b9192d5..0196b209bb19 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 13 -EXTRAVERSION =-rc4 +EXTRAVERSION =-rc5 NAME=Woozy Numbat # *DOCUMENTATION* -- cgit v1.2.3 From c1a15468d58e75debc5437b2e4e12d02a89bb3a2 Mon Sep 17 00:00:00 2001 From: Jack Hammer Date: Tue, 26 Jul 2005 10:20:33 -0400 Subject: [SCSI] ServeRAID V7.12.02 I am resubmitting the 2.6 kernel patch for the Version 7.12.02 ips driver. I have eliminated a couple of inappropriate changes pointed out by Arjan. Signed-off-by: Jack Hammer Signed-off-by: James Bottomley --- drivers/scsi/ips.c | 8 +++++--- drivers/scsi/ips.h | 39 +++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 6dfcb4fbccdd..4cdd891781b1 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -133,10 +133,12 @@ /* 6.10.00 - Remove 1G Addressing Limitations */ /* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 */ /* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 */ -/* 7.10.xx - Add highmem_io flag in SCSI Templete for 2.4 kernels */ +/* 7.10.18 - Add highmem_io flag in SCSI Templete for 2.4 kernels */ /* - Fix path/name for scsi_hosts.h include for 2.6 kernels */ /* - Fix sort order of 7k */ /* - Remove 3 unused "inline" functions */ +/* 7.12.xx - Use STATIC functions whereever possible */ +/* - Clean up deprecated MODULE_PARM calls */ /*****************************************************************************/ /* @@ -207,8 +209,8 @@ module_param(ips, charp, 0); /* * DRIVER_VER */ -#define IPS_VERSION_HIGH "7.10" -#define IPS_VERSION_LOW ".18 " +#define IPS_VERSION_HIGH "7.12" +#define IPS_VERSION_LOW ".02 " #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) #warning "This driver has only been tested on the x86/ia64/x86_64 platforms" diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 480e06f4d6ae..505e967013de 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -87,15 +87,14 @@ #define scsi_set_pci_device(sh,dev) (0) #endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - - #ifndef irqreturn_t - typedef void irqreturn_t; - #endif - + #ifndef IRQ_NONE + typedef void irqreturn_t; #define IRQ_NONE #define IRQ_HANDLED #define IRQ_RETVAL(x) + #endif + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #define IPS_REGISTER_HOSTS(SHT) scsi_register_module(MODULE_SCSI_HA,SHT) #define IPS_UNREGISTER_HOSTS(SHT) scsi_unregister_module(MODULE_SCSI_HA,SHT) #define IPS_ADD_HOST(shost,device) @@ -123,6 +122,10 @@ #ifndef min #define min(x,y) ((x) < (y) ? x : y) #endif + + #ifndef __iomem /* For clean compiles in earlier kernels without __iomem annotations */ + #define __iomem + #endif #define pci_dma_hi32(a) ((a >> 16) >> 16) #define pci_dma_lo32(a) (a & 0xffffffff) @@ -1206,13 +1209,13 @@ typedef struct { #define IPS_VER_MAJOR 7 #define IPS_VER_MAJOR_STRING "7" -#define IPS_VER_MINOR 10 -#define IPS_VER_MINOR_STRING "10" -#define IPS_VER_BUILD 18 -#define IPS_VER_BUILD_STRING "18" -#define IPS_VER_STRING "7.10.18" +#define IPS_VER_MINOR 12 +#define IPS_VER_MINOR_STRING "12" +#define IPS_VER_BUILD 02 +#define IPS_VER_BUILD_STRING "02" +#define IPS_VER_STRING "7.12.02" #define IPS_RELEASE_ID 0x00020000 -#define IPS_BUILD_IDENT 731 +#define IPS_BUILD_IDENT 761 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved." #define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved." #define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved." @@ -1223,12 +1226,12 @@ typedef struct { #define IPS_VER_SERVERAID2 "2.88.13" #define IPS_VER_NAVAJO "2.88.13" #define IPS_VER_SERVERAID3 "6.10.24" -#define IPS_VER_SERVERAID4H "7.10.11" -#define IPS_VER_SERVERAID4MLx "7.10.18" -#define IPS_VER_SARASOTA "7.10.18" -#define IPS_VER_MARCO "7.10.18" -#define IPS_VER_SEBRING "7.10.18" -#define IPS_VER_KEYWEST "7.10.18" +#define IPS_VER_SERVERAID4H "7.12.02" +#define IPS_VER_SERVERAID4MLx "7.12.02" +#define IPS_VER_SARASOTA "7.12.02" +#define IPS_VER_MARCO "7.12.02" +#define IPS_VER_SEBRING "7.12.02" +#define IPS_VER_KEYWEST "7.12.02" /* Compatability IDs for various adapters */ #define IPS_COMPAT_UNKNOWN "" -- cgit v1.2.3 From c2c96f46f46df072e49200a1181b3086cd2f08a6 Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Tue, 2 Aug 2005 12:21:51 +0300 Subject: [SCSI] Fix SCSI tape oops at module removal Removing the SCSI tape module results in an oops in class_device_destroy if any devices are present. The patch at the end of this message fixes the bug by moving class_destroy() later in exit_st() so that the class still exists when devices are removed. (The bug is old but class_simple_device_remove() did nothing when the class did not exist.) The patch also fixes a "class leak" in init_st() error path. I would like to get this into 2.6.13 but it may be too late? Signed-off-by: Kai Makisara Signed-off-by: James Bottomley --- drivers/scsi/st.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 0291a8fb654d..0a7839db5752 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4149,12 +4149,10 @@ static int __init init_st(void) do_create_driverfs_files(); return 0; } - if (st_sysfs_class) - class_destroy(st_sysfs_class); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), - ST_MAX_TAPE_ENTRIES); } + class_destroy(st_sysfs_class); printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR); return 1; @@ -4162,13 +4160,11 @@ static int __init init_st(void) static void __exit exit_st(void) { - if (st_sysfs_class) - class_destroy(st_sysfs_class); - st_sysfs_class = NULL; do_remove_driverfs_files(); scsi_unregister_driver(&st_template.gendrv); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES); + class_destroy(st_sysfs_class); kfree(scsi_tapes); printk(KERN_INFO "st: Unloaded.\n"); } -- cgit v1.2.3 From f7d1d23c301e0ce82c801f3b5800be6341752a1f Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 2 Aug 2005 21:51:36 +1000 Subject: [PATCH] Obvious bugfix for yenta resource allocation Recent changes (well, dating from 12 July) have broken cardbus on my powerbook: I get 3 messages saying "no resource of type xxx available, trying to continue", and if I plug in my wireless card, it complains that there are no resources allocated to the card. This all worked in 2.6.12. Looking at the code in yenta_socket.c, function yenta_allocate_res, it's obvious what is wrong: if we get to line 639 (i.e. there wasn't a usable preassigned resource), we will always flow through to line 668, which is the printk that I was seeing, even if a resource was successfully allocated. It looks to me as though there should be a return statement after the two config_writel's in each of the 3 branches of the if statements, so that the function returns after successfully setting up the resource. The patch below adds these return statements, and with this patch, cardbus works on my powerbook once again. Signed-off-by: Paul Mackerras Acked-by: Dominik Brodowski Signed-off-by: Linus Torvalds --- drivers/pcmcia/yenta_socket.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 6837491f021c..91e7457d5b04 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -642,6 +642,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); + return; } } else { if (type & IORESOURCE_PREFETCH) { @@ -650,6 +651,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); + return; } /* Approximating prefetchable by non-prefetchable */ res->flags = IORESOURCE_MEM; @@ -659,6 +661,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { config_writel(socket, addr_start, res->start); config_writel(socket, addr_end, res->end); + return; } } -- cgit v1.2.3 From f7c80c9f77b0e8a59a19506fd3caf323408a5166 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Tue, 19 Jul 2005 20:04:24 +0200 Subject: [PATCH] aic byteorder fixes after recent cleanup Rebuild the aic7xxx firmware doesn't work anymore after this change which appeared int 2.6.13-rc1: [SCSI] aic7xxx/aic79xx: remove useless byte order macro cruft Two files did not include byteorder.h, resulting in aic dying with a panic "Unknown opcode encountered in seq program" This fixes it for me. Signed-off-by: Olaf Hering Acked-by: Christoph Hellwig Signed-off-by: Linus Torvalds --- drivers/scsi/aic7xxx/aicasm/aicasm.c | 4 ++-- drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c index c34639481904..f936b691232f 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm.c +++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c @@ -369,7 +369,7 @@ output_code() fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x", cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n", -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN cur_instr->format.bytes[0], cur_instr->format.bytes[1], cur_instr->format.bytes[2], @@ -613,7 +613,7 @@ output_listing(char *ifilename) line++; } fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN cur_instr->format.bytes[0], cur_instr->format.bytes[1], cur_instr->format.bytes[2], diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h index 3e80f07df49c..e64f802bbaaa 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h @@ -42,8 +42,10 @@ * $FreeBSD$ */ +#include + struct ins_format1 { -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN uint32_t immediate : 8, source : 9, destination : 9, @@ -61,7 +63,7 @@ struct ins_format1 { }; struct ins_format2 { -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN uint32_t shift_control : 8, source : 9, destination : 9, @@ -79,7 +81,7 @@ struct ins_format2 { }; struct ins_format3 { -#if BYTE_ORDER == LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN uint32_t immediate : 8, source : 9, address : 10, -- cgit v1.2.3 From 84e66ee7ec7aaa789945403b7cbde7a0b08c15ef Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 2 Aug 2005 09:32:17 -0500 Subject: [SCSI] aic7xxx: final fixes for DT handling The aic7xxx can support Data Group transfers at periods > 12.5, so eliminate that restriction. Additionally wide is a requirement for DT so ensure wide is set if users request DT. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index d0d0b84a31f4..d79a2ae89979 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -2429,16 +2429,16 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) unsigned int ppr_options = tinfo->goal.ppr_options & ~MSG_EXT_PPR_DT_REQ; unsigned int period = tinfo->goal.period; + unsigned int width = tinfo->goal.width; unsigned long flags; struct ahc_syncrate *syncrate; if (dt) { - period = 9; /* 12.5ns is the only period valid for DT */ ppr_options |= MSG_EXT_PPR_DT_REQ; - } else if (period == 9) { + if (!width) + ahc_linux_set_width(starget, 1); + } else if (period == 9) period = 10; /* if resetting DT, period must be >= 25ns */ - ppr_options &= ~MSG_EXT_PPR_DT_REQ; - } ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); -- cgit v1.2.3 From d7ed538a02c219119adb20f1dccbf0f8015e53f3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 2 Aug 2005 20:08:02 +0200 Subject: [PATCH] cfq-iosched: fix problem with barriers and max_depth == 1 CFQ will currently stall when using write barriers and the default max_depth setting of 1, since we artificially need a depth of 2 when pre-pending the first flush. So never deny the barrier request going to the device. This is a regression since 2.6.12, it was found in SUSE testing. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds --- drivers/block/cfq-iosched.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index de5746e38af9..2435a7c99b2b 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c @@ -1281,6 +1281,7 @@ dispatch: */ if (!cfq_crq_in_driver(crq) && !cfq_cfqq_idle_window(cfqq) && + !blk_barrier_rq(rq) && cfqd->rq_in_driver >= cfqd->cfq_max_depth) return NULL; -- cgit v1.2.3 From 688d191821de7893043f5a37970472627aaffa4e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 2 Aug 2005 14:55:40 -0700 Subject: pci: make bus resource start address override minimum IO address The reason we have PCIBIOS_MIN_IO and PCIBIOS_MIN_CARDBUS_IO is because we want to protect badly documented motherboard PCI resources and thus don't want to allocate new resources in low IO/MEM space. However, if we have already discovered a PCI bridge with a specified resource base, that should override that decision. This change will allow us to move the "careful" region upwards without resulting in problems allocating resources in low mappings. This was brought on by us having allocated a bus resource at 0x1000, conflicting with a undocumented VAIO Sony PI resources. --- drivers/pci/bus.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index fedae89d8f7d..fb9a11243d2a 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -60,7 +60,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, continue; /* Ok, try it out.. */ - ret = allocate_resource(r, res, size, min, -1, align, + ret = allocate_resource(r, res, size, + r->start ? : min, + -1, align, alignf, alignf_data); if (ret == 0) break; -- cgit v1.2.3 From 71db63acff69618b3d9d3114bd061938150e146b Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Wed, 3 Aug 2005 02:59:47 +0400 Subject: [PATCH] increase PCIBIOS_MIN_IO on x86 There is a number of x86 laptops that have some non-PCI IO ports in the 0x1000-0x1fff range, and it's quite hard to control the correct order of resource allocation between PCI and other subsystems controlling these ports. Especially with modular kernel. So just increase PCIBIOS_MIN_IO to 0x4000 to prevent any new PCI resource allocations in the problematic range (this limitation must apply _only_ to the root bus resources - see Linus' change in pci_bus_alloc_resource). As PCIBIOS_MIN_IO and PCIBIOS_MIN_CARDBUS_IO are the same now on i386 and x86-64, we can remove the latter. Signed-off-by: Ivan Kokshaysky Signed-off-by: Linus Torvalds --- include/asm-i386/pci.h | 4 +--- include/asm-x86_64/pci.h | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h index 78c85985aee3..2cbab30734d6 100644 --- a/include/asm-i386/pci.h +++ b/include/asm-i386/pci.h @@ -18,11 +18,9 @@ extern unsigned int pcibios_assign_all_busses(void); #define pcibios_scan_all_fns(a, b) 0 extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x1000 +#define PCIBIOS_MIN_IO 0x4000 #define PCIBIOS_MIN_MEM (pci_mem_start) -#define PCIBIOS_MIN_CARDBUS_IO 0x4000 - void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h index eeb3088a1c9e..9c4527eb55e2 100644 --- a/include/asm-x86_64/pci.h +++ b/include/asm-x86_64/pci.h @@ -22,11 +22,9 @@ extern unsigned int pcibios_assign_all_busses(void); extern int no_iommu, force_iommu; extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x1000 +#define PCIBIOS_MIN_IO 0x4000 #define PCIBIOS_MIN_MEM (pci_mem_start) -#define PCIBIOS_MIN_CARDBUS_IO 0x4000 - void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value); -- cgit v1.2.3 From 0b2bfb4e7ff61f286676867c3508569bea6fbf7a Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Wed, 3 Aug 2005 03:09:03 +0400 Subject: [PATCH] ACPI: increase PCIBIOS_MIN_IO on x86 We have increased PCIBIOS_MIN_IO to 0x4000, but still want motherboard resources to be allocated properly. So we need to state 0x1000 (according to the comment) limit explicitely. Signed-off-by: Ivan Kokshaysky Signed-off-by: Linus Torvalds --- drivers/acpi/motherboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index 61ea70742d49..2934475d67d6 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -43,7 +43,7 @@ ACPI_MODULE_NAME ("acpi_motherboard") */ #define IS_RESERVED_ADDR(base, len) \ (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \ - && ((base) + (len) > PCIBIOS_MIN_IO)) + && ((base) + (len) > 0x1000)) /* * Clearing the flag (IORESOURCE_BUSY) allows drivers to use -- cgit v1.2.3 From 3d35600a9de8e2816d0e3726f64b7271af6fdda4 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 3 Aug 2005 00:22:52 -0400 Subject: [ACPI] fix 64-bit build warning in processor_idle.c Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index fd5458947851..8f7836678b29 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -86,12 +86,11 @@ static int set_max_cstate(struct dmi_system_id *id) if (max_cstate > ACPI_PROCESSOR_MAX_POWER) return 0; - printk(KERN_NOTICE PREFIX "%s detected - %s disabled." + printk(KERN_NOTICE PREFIX "%s detected - limiting to C%ld max_cstate." " Override with \"processor.max_cstate=%d\"\n", id->ident, - ((int)id->driver_data == 1)? "C2,C3":"C3", - ACPI_PROCESSOR_MAX_POWER + 1); + (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1); - max_cstate = (int)id->driver_data; + max_cstate = (long)id->driver_data; return 0; } -- cgit v1.2.3 From 5cb4cc0d8211c490537c8568001958fc76741312 Mon Sep 17 00:00:00 2001 From: Haren Myneni Date: Wed, 3 Aug 2005 15:08:18 +1000 Subject: [PATCH] Xmon bug fix for soft-reset For soft reset during system hang, got an error "CPU did not take control" for some CPUs even though they responded to soft-reset (called SystemReset, die and called debugger - xmon). First these CPUs entered into xmon by IPI callback and then got a soft-reset exception and re-entered into xmon again. The first CPU which re-entered into xmon got the output lock and made into xmon successfully without unlocking. Hence, the next CPU(s) which re-entered into xmon try to acquire a lock (get_output_lock). Therefore, we can not view state of those CPU(s). [This is a simple, very low risk, obvious fix for an obvious bug, and should go into 2.6.13. -- paulus] Signed-off-by: Haren Myneni Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- arch/ppc64/xmon/xmon.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c index 7f6e13a4b71e..05539439e6bc 100644 --- a/arch/ppc64/xmon/xmon.c +++ b/arch/ppc64/xmon/xmon.c @@ -329,13 +329,16 @@ int xmon_core(struct pt_regs *regs, int fromipi) printf("cpu 0x%x: Exception %lx %s in xmon, " "returning to main loop\n", cpu, regs->trap, getvecname(TRAP(regs))); + release_output_lock(); longjmp(xmon_fault_jmp[cpu], 1); } if (setjmp(recurse_jmp) != 0) { if (!in_xmon || !xmon_gate) { + get_output_lock(); printf("xmon: WARNING: bad recursive fault " "on cpu 0x%x\n", cpu); + release_output_lock(); goto waiting; } secondary = !(xmon_taken && cpu == xmon_owner); -- cgit v1.2.3 From ecc21ebe603af31f172c43b8b261df79040790ef Mon Sep 17 00:00:00 2001 From: David Shaohua Li Date: Wed, 3 Aug 2005 11:00:11 -0400 Subject: [ACPI] PCI interrupt link suspend/resume - revert to 2.6.12 behaviour This patch disables the PCI Interrupt Link refernece counts, which should not co-exist with the 2.6.12 irq_router.resume method or else a double acpi_pci_link_set() could result on resume. Signed-off-by: David Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 6a29610edc11..0091dbdf7ef9 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -692,7 +692,18 @@ acpi_pci_link_free_irq(acpi_handle handle) return_VALUE(-1); } +#ifdef FUTURE_USE + /* + * The Link reference count allows us to _DISable an unused link + * and suspend time, and set it again on resume. + * However, 2.6.12 still has irq_router.resume + * which blindly restores the link state. + * So we disable the reference count method + * to prevent duplicate acpi_pci_link_set() + * which would harm some systems + */ link->refcnt --; +#endif ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link %s is dereferenced\n", acpi_device_bid(link->device))); -- cgit v1.2.3 From f33ea7f404e592e4563b12101b7a4d17da6558d7 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 3 Aug 2005 20:24:01 +1000 Subject: [PATCH] fix get_user_pages bug Checking pte_dirty instead of pte_write in __follow_page is problematic for s390, and for copy_one_pte which leaves dirty when clearing write. So revert __follow_page to check pte_write as before, and make do_wp_page pass back a special extra VM_FAULT_WRITE bit to say it has done its full job: once get_user_pages receives this value, it no longer requires pte_write in __follow_page. But most callers of handle_mm_fault, in the various architectures, have switch statements which do not expect this new case. To avoid changing them all in a hurry, make an inline wrapper function (using the old name) that masks off the new bit, and use the extended interface with double underscores. Yes, we do have a call to do_wp_page from do_swap_page, but no need to change that: in rare case it's needed, another do_wp_page will follow. Signed-off-by: Hugh Dickins [ Cleanups by Nick Piggin ] Signed-off-by: Linus Torvalds --- include/linux/mm.h | 22 +++++++++++++++++----- mm/memory.c | 31 +++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 6eb7f48317f8..82d7024f0765 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -625,10 +625,16 @@ static inline int page_mapped(struct page *page) * Used to decide whether a process gets delivered SIGBUS or * just gets major/minor fault counters bumped up. */ -#define VM_FAULT_OOM (-1) -#define VM_FAULT_SIGBUS 0 -#define VM_FAULT_MINOR 1 -#define VM_FAULT_MAJOR 2 +#define VM_FAULT_OOM 0x00 +#define VM_FAULT_SIGBUS 0x01 +#define VM_FAULT_MINOR 0x02 +#define VM_FAULT_MAJOR 0x03 + +/* + * Special case for get_user_pages. + * Must be in a distinct bit from the above VM_FAULT_ flags. + */ +#define VM_FAULT_WRITE 0x10 #define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) @@ -704,7 +710,13 @@ extern pte_t *FASTCALL(pte_alloc_kernel(struct mm_struct *mm, pmd_t *pmd, unsign extern pte_t *FASTCALL(pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address)); extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot); extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot); -extern int handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access); +extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access); + +static inline int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access) +{ + return __handle_mm_fault(mm, vma, address, write_access) & (~VM_FAULT_WRITE); +} + extern int make_pages_present(unsigned long addr, unsigned long end); extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); void install_arg_page(struct vm_area_struct *, struct page *, unsigned long); diff --git a/mm/memory.c b/mm/memory.c index 2405289dfdf8..81d7117aa58b 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -811,15 +811,18 @@ static struct page *__follow_page(struct mm_struct *mm, unsigned long address, pte = *ptep; pte_unmap(ptep); if (pte_present(pte)) { - if (write && !pte_dirty(pte)) + if (write && !pte_write(pte)) goto out; if (read && !pte_read(pte)) goto out; pfn = pte_pfn(pte); if (pfn_valid(pfn)) { page = pfn_to_page(pfn); - if (accessed) + if (accessed) { + if (write && !pte_dirty(pte) &&!PageDirty(page)) + set_page_dirty(page); mark_page_accessed(page); + } return page; } } @@ -941,10 +944,11 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, } spin_lock(&mm->page_table_lock); do { + int write_access = write; struct page *page; cond_resched_lock(&mm->page_table_lock); - while (!(page = follow_page(mm, start, write))) { + while (!(page = follow_page(mm, start, write_access))) { /* * Shortcut for anonymous pages. We don't want * to force the creation of pages tables for @@ -957,7 +961,16 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, break; } spin_unlock(&mm->page_table_lock); - switch (handle_mm_fault(mm,vma,start,write)) { + switch (__handle_mm_fault(mm, vma, start, + write_access)) { + case VM_FAULT_WRITE: + /* + * do_wp_page has broken COW when + * necessary, even if maybe_mkwrite + * decided not to set pte_write + */ + write_access = 0; + /* FALLTHRU */ case VM_FAULT_MINOR: tsk->min_flt++; break; @@ -1220,6 +1233,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, struct page *old_page, *new_page; unsigned long pfn = pte_pfn(pte); pte_t entry; + int ret; if (unlikely(!pfn_valid(pfn))) { /* @@ -1247,7 +1261,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, lazy_mmu_prot_update(entry); pte_unmap(page_table); spin_unlock(&mm->page_table_lock); - return VM_FAULT_MINOR; + return VM_FAULT_MINOR|VM_FAULT_WRITE; } } pte_unmap(page_table); @@ -1274,6 +1288,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, /* * Re-check the pte - we dropped the lock */ + ret = VM_FAULT_MINOR; spin_lock(&mm->page_table_lock); page_table = pte_offset_map(pmd, address); if (likely(pte_same(*page_table, pte))) { @@ -1290,12 +1305,13 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, /* Free the old page.. */ new_page = old_page; + ret |= VM_FAULT_WRITE; } pte_unmap(page_table); page_cache_release(new_page); page_cache_release(old_page); spin_unlock(&mm->page_table_lock); - return VM_FAULT_MINOR; + return ret; no_new_page: page_cache_release(old_page); @@ -1987,7 +2003,6 @@ static inline int handle_pte_fault(struct mm_struct *mm, if (write_access) { if (!pte_write(entry)) return do_wp_page(mm, vma, address, pte, pmd, entry); - entry = pte_mkdirty(entry); } entry = pte_mkyoung(entry); @@ -2002,7 +2017,7 @@ static inline int handle_pte_fault(struct mm_struct *mm, /* * By the time we get here, we already hold the mm semaphore */ -int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, +int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, unsigned long address, int write_access) { pgd_t *pgd; -- cgit v1.2.3 From a68d2ebc1581a3aec57bd032651e013fa609f530 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 3 Aug 2005 10:07:09 -0700 Subject: Fix up recent get_user_pages() handling The VM_FAULT_WRITE thing is an extra bit, not a valid return value, and has to be treated as such by get_user_pages(). Signed-off-by: Linus Torvalds --- mm/memory.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 81d7117aa58b..e046b7e4b530 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -949,6 +949,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, cond_resched_lock(&mm->page_table_lock); while (!(page = follow_page(mm, start, write_access))) { + int ret; + /* * Shortcut for anonymous pages. We don't want * to force the creation of pages tables for @@ -961,16 +963,18 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, break; } spin_unlock(&mm->page_table_lock); - switch (__handle_mm_fault(mm, vma, start, - write_access)) { - case VM_FAULT_WRITE: - /* - * do_wp_page has broken COW when - * necessary, even if maybe_mkwrite - * decided not to set pte_write - */ + ret = __handle_mm_fault(mm, vma, start, write_access); + + /* + * The VM_FAULT_WRITE bit tells us that do_wp_page has + * broken COW when necessary, even if maybe_mkwrite + * decided not to set pte_write. We can thus safely do + * subsequent page lookups as if they were reads. + */ + if (ret & VM_FAULT_WRITE) write_access = 0; - /* FALLTHRU */ + + switch (ret & ~VM_FAULT_WRITE) { case VM_FAULT_MINOR: tsk->min_flt++; break; -- cgit v1.2.3 From 1fcf844861eb08ee05e05dba13b5436f2f2e29ed Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 3 Aug 2005 19:49:16 +0100 Subject: [PATCH] ARM: 2832/1: BAST - limit clock-rate for IIC bus Patch from Ben Dooks The default clock rate does not specify a maximum, so the default of 400KHz is used. This rate is too fast for the PMU on the EB2410ITX, so we now specify platform data with a rate of around 100KHz. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/mach-bast.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 1e7f343822d0..e9182242da95 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -30,6 +30,7 @@ * 28-Jun-2005 BJD Moved pm functionality out to common code * 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s * 25-Jul-2005 BJD Removed ASIX static mappings + * 27-Jul-2005 BJD Ensure maximum frequency of i2c bus */ #include @@ -60,6 +61,7 @@ #include #include #include +#include #include #include @@ -304,7 +306,7 @@ static void bast_nand_select(struct s3c2410_nand_set *set, int slot) } static struct s3c2410_platform_nand bast_nand_info = { - .tacls = 80, + .tacls = 40, .twrph0 = 80, .twrph1 = 80, .nr_sets = ARRAY_SIZE(bast_nand_sets), @@ -385,6 +387,17 @@ static struct platform_device bast_sio = { }, }; +/* we have devices on the bus which cannot work much over the + * standard 100KHz i2c bus frequency +*/ + +static struct s3c2410_platform_i2c bast_i2c_info = { + .flags = 0, + .slave_addr = 0x10, + .bus_freq = 100*1000, + .max_freq = 130*1000, +}; + /* Standard BAST devices */ static struct platform_device *bast_devices[] __initdata = { @@ -431,6 +444,7 @@ void __init bast_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c_device_nand.dev.platform_data = &bast_nand_info; + s3c_device_i2c.dev.platform_data = &bast_i2c_info; s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); s3c24xx_init_clocks(0); -- cgit v1.2.3 From f148af2593ef76ac705d1cc6abe48f455c9912cc Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Wed, 3 Aug 2005 19:49:17 +0100 Subject: [PATCH] ARM: 2837/2: Re: ARM: Make NWFPE preempt safe Patch from Richard Purdie NWFPE used global variables which meant it wasn't safe for use with preemptive kernels. This patch removes them and communicates the information between functions in a preempt safe manner. Generation of some exceptions was broken and this has also been corrected. Tests with glibc's maths test suite show no change in the results before/after this patch. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/nwfpe/double_cpdo.c | 24 +-- arch/arm/nwfpe/extended_cpdo.c | 24 +-- arch/arm/nwfpe/fpa11.c | 30 ++-- arch/arm/nwfpe/fpa11.h | 11 +- arch/arm/nwfpe/fpa11_cpdo.c | 28 ++-- arch/arm/nwfpe/fpa11_cpdt.c | 22 ++- arch/arm/nwfpe/fpa11_cprt.c | 28 ++-- arch/arm/nwfpe/fpmodule.c | 15 +- arch/arm/nwfpe/single_cpdo.c | 24 +-- arch/arm/nwfpe/softfloat.c | 334 ++++++++++++++++++++--------------------- arch/arm/nwfpe/softfloat.h | 68 ++++----- 11 files changed, 304 insertions(+), 304 deletions(-) diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c index 7ffd8cb9bc96..c51d1386a97c 100644 --- a/arch/arm/nwfpe/double_cpdo.c +++ b/arch/arm/nwfpe/double_cpdo.c @@ -40,17 +40,17 @@ float64 float64_arccos(float64 rFm); float64 float64_pow(float64 rFn, float64 rFm); float64 float64_pol(float64 rFn, float64 rFm); -static float64 float64_rsf(float64 rFn, float64 rFm) +static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm) { - return float64_sub(rFm, rFn); + return float64_sub(roundData, rFm, rFn); } -static float64 float64_rdv(float64 rFn, float64 rFm) +static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm) { - return float64_div(rFm, rFn); + return float64_div(roundData, rFm, rFn); } -static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = { +static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = { [ADF_CODE >> 20] = float64_add, [MUF_CODE >> 20] = float64_mul, [SUF_CODE >> 20] = float64_sub, @@ -65,12 +65,12 @@ static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = { [FRD_CODE >> 20] = float64_rdv, }; -static float64 float64_mvf(float64 rFm) +static float64 float64_mvf(struct roundingData *roundData,float64 rFm) { return rFm; } -static float64 float64_mnf(float64 rFm) +static float64 float64_mnf(struct roundingData *roundData,float64 rFm) { union float64_components u; @@ -84,7 +84,7 @@ static float64 float64_mnf(float64 rFm) return u.f64; } -static float64 float64_abs(float64 rFm) +static float64 float64_abs(struct roundingData *roundData,float64 rFm) { union float64_components u; @@ -98,7 +98,7 @@ static float64 float64_abs(float64 rFm) return u.f64; } -static float64 (*const monadic_double[16])(float64 rFm) = { +static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = { [MVF_CODE >> 20] = float64_mvf, [MNF_CODE >> 20] = float64_mnf, [ABS_CODE >> 20] = float64_abs, @@ -108,7 +108,7 @@ static float64 (*const monadic_double[16])(float64 rFm) = { [NRM_CODE >> 20] = float64_mvf, }; -unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd) +unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) { FPA11 *fpa11 = GET_FPA11(); float64 rFm; @@ -151,13 +151,13 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd) } if (dyadic_double[opc_mask_shift]) { - rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm); + rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm); } else { return 0; } } else { if (monadic_double[opc_mask_shift]) { - rFd->fDouble = monadic_double[opc_mask_shift](rFm); + rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm); } else { return 0; } diff --git a/arch/arm/nwfpe/extended_cpdo.c b/arch/arm/nwfpe/extended_cpdo.c index c39f68a3449e..65a279ba927f 100644 --- a/arch/arm/nwfpe/extended_cpdo.c +++ b/arch/arm/nwfpe/extended_cpdo.c @@ -35,17 +35,17 @@ floatx80 floatx80_arccos(floatx80 rFm); floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm); floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm); -static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm) +static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) { - return floatx80_sub(rFm, rFn); + return floatx80_sub(roundData, rFm, rFn); } -static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm) +static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm) { - return floatx80_div(rFm, rFn); + return floatx80_div(roundData, rFm, rFn); } -static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = { +static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = { [ADF_CODE >> 20] = floatx80_add, [MUF_CODE >> 20] = floatx80_mul, [SUF_CODE >> 20] = floatx80_sub, @@ -60,24 +60,24 @@ static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = { [FRD_CODE >> 20] = floatx80_rdv, }; -static floatx80 floatx80_mvf(floatx80 rFm) +static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm) { return rFm; } -static floatx80 floatx80_mnf(floatx80 rFm) +static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm) { rFm.high ^= 0x8000; return rFm; } -static floatx80 floatx80_abs(floatx80 rFm) +static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm) { rFm.high &= 0x7fff; return rFm; } -static floatx80 (*const monadic_extended[16])(floatx80 rFm) = { +static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = { [MVF_CODE >> 20] = floatx80_mvf, [MNF_CODE >> 20] = floatx80_mnf, [ABS_CODE >> 20] = floatx80_abs, @@ -87,7 +87,7 @@ static floatx80 (*const monadic_extended[16])(floatx80 rFm) = { [NRM_CODE >> 20] = floatx80_mvf, }; -unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd) +unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) { FPA11 *fpa11 = GET_FPA11(); floatx80 rFm; @@ -138,13 +138,13 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd) } if (dyadic_extended[opc_mask_shift]) { - rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm); + rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm); } else { return 0; } } else { if (monadic_extended[opc_mask_shift]) { - rFd->fExtended = monadic_extended[opc_mask_shift](rFm); + rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm); } else { return 0; } diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c index bf61696865ec..7690f731ee87 100644 --- a/arch/arm/nwfpe/fpa11.c +++ b/arch/arm/nwfpe/fpa11.c @@ -51,48 +51,42 @@ static void resetFPA11(void) fpa11->fpsr = FP_EMULATOR | BIT_AC; } -void SetRoundingMode(const unsigned int opcode) +int8 SetRoundingMode(const unsigned int opcode) { switch (opcode & MASK_ROUNDING_MODE) { default: case ROUND_TO_NEAREST: - float_rounding_mode = float_round_nearest_even; - break; + return float_round_nearest_even; case ROUND_TO_PLUS_INFINITY: - float_rounding_mode = float_round_up; - break; + return float_round_up; case ROUND_TO_MINUS_INFINITY: - float_rounding_mode = float_round_down; - break; + return float_round_down; case ROUND_TO_ZERO: - float_rounding_mode = float_round_to_zero; - break; + return float_round_to_zero; } } -void SetRoundingPrecision(const unsigned int opcode) +int8 SetRoundingPrecision(const unsigned int opcode) { #ifdef CONFIG_FPE_NWFPE_XP switch (opcode & MASK_ROUNDING_PRECISION) { case ROUND_SINGLE: - floatx80_rounding_precision = 32; - break; + return 32; case ROUND_DOUBLE: - floatx80_rounding_precision = 64; - break; + return 64; case ROUND_EXTENDED: - floatx80_rounding_precision = 80; - break; + return 80; default: - floatx80_rounding_precision = 80; + return 80; } #endif + return 80; } void nwfpe_init_fpa(union fp_state *fp) @@ -103,8 +97,6 @@ void nwfpe_init_fpa(union fp_state *fp) #endif memset(fpa11, 0, sizeof(FPA11)); resetFPA11(); - SetRoundingMode(ROUND_TO_NEAREST); - SetRoundingPrecision(ROUND_EXTENDED); fpa11->initflag = 1; } diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index e4a61aea534b..93523ae4b7a1 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -37,6 +37,13 @@ /* includes */ #include "fpsr.h" /* FP control and status register definitions */ #include "milieu.h" + +struct roundingData { + int8 mode; + int8 precision; + signed char exception; +}; + #include "softfloat.h" #define typeNone 0x00 @@ -84,8 +91,8 @@ typedef struct tagFPA11 { initialised. */ } FPA11; -extern void SetRoundingMode(const unsigned int); -extern void SetRoundingPrecision(const unsigned int); +extern int8 SetRoundingMode(const unsigned int); +extern int8 SetRoundingPrecision(const unsigned int); extern void nwfpe_init_fpa(union fp_state *fp); #endif diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c index 1bea67437b6f..4a31dfd94068 100644 --- a/arch/arm/nwfpe/fpa11_cpdo.c +++ b/arch/arm/nwfpe/fpa11_cpdo.c @@ -24,15 +24,16 @@ #include "fpa11.h" #include "fpopcode.h" -unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd); -unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd); -unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd); +unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd); +unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd); +unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd); unsigned int EmulateCPDO(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); FPREG *rFd; unsigned int nType, nDest, nRc; + struct roundingData roundData; /* Get the destination size. If not valid let Linux perform an invalid instruction trap. */ @@ -40,7 +41,9 @@ unsigned int EmulateCPDO(const unsigned int opcode) if (typeNone == nDest) return 0; - SetRoundingMode(opcode); + roundData.mode = SetRoundingMode(opcode); + roundData.precision = SetRoundingPrecision(opcode); + roundData.exception = 0; /* Compare the size of the operands in Fn and Fm. Choose the largest size and perform operations in that size, @@ -63,14 +66,14 @@ unsigned int EmulateCPDO(const unsigned int opcode) switch (nType) { case typeSingle: - nRc = SingleCPDO(opcode, rFd); + nRc = SingleCPDO(&roundData, opcode, rFd); break; case typeDouble: - nRc = DoubleCPDO(opcode, rFd); + nRc = DoubleCPDO(&roundData, opcode, rFd); break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - nRc = ExtendedCPDO(opcode, rFd); + nRc = ExtendedCPDO(&roundData, opcode, rFd); break; #endif default: @@ -93,9 +96,9 @@ unsigned int EmulateCPDO(const unsigned int opcode) case typeSingle: { if (typeDouble == nType) - rFd->fSingle = float64_to_float32(rFd->fDouble); + rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble); else - rFd->fSingle = floatx80_to_float32(rFd->fExtended); + rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended); } break; @@ -104,7 +107,7 @@ unsigned int EmulateCPDO(const unsigned int opcode) if (typeSingle == nType) rFd->fDouble = float32_to_float64(rFd->fSingle); else - rFd->fDouble = floatx80_to_float64(rFd->fExtended); + rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended); } break; @@ -121,12 +124,15 @@ unsigned int EmulateCPDO(const unsigned int opcode) #else if (nDest != nType) { if (nDest == typeSingle) - rFd->fSingle = float64_to_float32(rFd->fDouble); + rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble); else rFd->fDouble = float32_to_float64(rFd->fSingle); } #endif } + if (roundData.exception) + float_raise(roundData.exception); + return nRc; } diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c index 95fb63fa9d18..b0db5cbcc3b1 100644 --- a/arch/arm/nwfpe/fpa11_cpdt.c +++ b/arch/arm/nwfpe/fpa11_cpdt.c @@ -96,7 +96,7 @@ static inline void loadMultiple(const unsigned int Fn, const unsigned int __user } } -static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem) +static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); union { @@ -106,12 +106,12 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem) switch (fpa11->fType[Fn]) { case typeDouble: - val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble); + val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble); break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended); + val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended); break; #endif @@ -122,7 +122,7 @@ static inline void storeSingle(const unsigned int Fn, unsigned int __user *pMem) put_user(val.i[0], pMem); } -static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem) +static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) { FPA11 *fpa11 = GET_FPA11(); union { @@ -137,7 +137,7 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem) #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: - val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended); + val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended); break; #endif @@ -259,8 +259,11 @@ unsigned int PerformSTF(const unsigned int opcode) { unsigned int __user *pBase, *pAddress, *pFinal; unsigned int nRc = 1, write_back = WRITE_BACK(opcode); + struct roundingData roundData; - SetRoundingMode(ROUND_TO_NEAREST); + roundData.mode = SetRoundingMode(opcode); + roundData.precision = SetRoundingPrecision(opcode); + roundData.exception = 0; pBase = (unsigned int __user *) readRegister(getRn(opcode)); if (REG_PC == getRn(opcode)) { @@ -281,10 +284,10 @@ unsigned int PerformSTF(const unsigned int opcode) switch (opcode & MASK_TRANSFER_LENGTH) { case TRANSFER_SINGLE: - storeSingle(getFd(opcode), pAddress); + storeSingle(&roundData, getFd(opcode), pAddress); break; case TRANSFER_DOUBLE: - storeDouble(getFd(opcode), pAddress); + storeDouble(&roundData, getFd(opcode), pAddress); break; #ifdef CONFIG_FPE_NWFPE_XP case TRANSFER_EXTENDED: @@ -295,6 +298,9 @@ unsigned int PerformSTF(const unsigned int opcode) nRc = 0; } + if (roundData.exception) + float_raise(roundData.exception); + if (write_back) writeRegister(getRn(opcode), (unsigned long) pFinal); return nRc; diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c index db01fbc97216..adf8d3000540 100644 --- a/arch/arm/nwfpe/fpa11_cprt.c +++ b/arch/arm/nwfpe/fpa11_cprt.c @@ -33,8 +33,6 @@ extern flag floatx80_is_nan(floatx80); extern flag float64_is_nan(float64); extern flag float32_is_nan(float32); -void SetRoundingMode(const unsigned int opcode); - unsigned int PerformFLT(const unsigned int opcode); unsigned int PerformFIX(const unsigned int opcode); @@ -77,14 +75,17 @@ unsigned int EmulateCPRT(const unsigned int opcode) unsigned int PerformFLT(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); - SetRoundingMode(opcode); - SetRoundingPrecision(opcode); + struct roundingData roundData; + + roundData.mode = SetRoundingMode(opcode); + roundData.precision = SetRoundingPrecision(opcode); + roundData.exception = 0; switch (opcode & MASK_ROUNDING_PRECISION) { case ROUND_SINGLE: { fpa11->fType[getFn(opcode)] = typeSingle; - fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode))); + fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(&roundData, readRegister(getRd(opcode))); } break; @@ -108,6 +109,9 @@ unsigned int PerformFLT(const unsigned int opcode) return 0; } + if (roundData.exception) + float_raise(roundData.exception); + return 1; } @@ -115,26 +119,29 @@ unsigned int PerformFIX(const unsigned int opcode) { FPA11 *fpa11 = GET_FPA11(); unsigned int Fn = getFm(opcode); + struct roundingData roundData; - SetRoundingMode(opcode); + roundData.mode = SetRoundingMode(opcode); + roundData.precision = SetRoundingPrecision(opcode); + roundData.exception = 0; switch (fpa11->fType[Fn]) { case typeSingle: { - writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle)); + writeRegister(getRd(opcode), float32_to_int32(&roundData, fpa11->fpreg[Fn].fSingle)); } break; case typeDouble: { - writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble)); + writeRegister(getRd(opcode), float64_to_int32(&roundData, fpa11->fpreg[Fn].fDouble)); } break; #ifdef CONFIG_FPE_NWFPE_XP case typeExtended: { - writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended)); + writeRegister(getRd(opcode), floatx80_to_int32(&roundData, fpa11->fpreg[Fn].fExtended)); } break; #endif @@ -143,6 +150,9 @@ unsigned int PerformFIX(const unsigned int opcode) return 0; } + if (roundData.exception) + float_raise(roundData.exception); + return 1; } diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index 12885f31d347..2dfe1ac42ee8 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c @@ -116,8 +116,6 @@ fpmodule.c to integrate with the NetBSD kernel (I hope!). code to access data in user space in some other source files at the moment (grep for get_user / put_user calls). --philb] -float_exception_flags is a global variable in SoftFloat. - This function is called by the SoftFloat routines to raise a floating point exception. We check the trap enable byte in the FPSR, and raise a SIGFPE exception if necessary. If not the relevant bits in the @@ -129,15 +127,14 @@ void float_raise(signed char flags) register unsigned int fpsr, cumulativeTraps; #ifdef CONFIG_DEBUG_USER - printk(KERN_DEBUG - "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n", - current->comm, current->pid, flags, - __builtin_return_address(0), GET_USERREG()->ARM_pc); + /* Ignore inexact errors as there are far too many of them to log */ + if (flags & ~BIT_IXC) + printk(KERN_DEBUG + "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n", + current->comm, current->pid, flags, + __builtin_return_address(0), GET_USERREG()->ARM_pc); #endif - /* Keep SoftFloat exception flags up to date. */ - float_exception_flags |= flags; - /* Read fpsr and initialize the cumulativeTraps. */ fpsr = readFPSR(); cumulativeTraps = 0; diff --git a/arch/arm/nwfpe/single_cpdo.c b/arch/arm/nwfpe/single_cpdo.c index 705808e88d9d..c66981d682cf 100644 --- a/arch/arm/nwfpe/single_cpdo.c +++ b/arch/arm/nwfpe/single_cpdo.c @@ -36,17 +36,17 @@ float32 float32_arccos(float32 rFm); float32 float32_pow(float32 rFn, float32 rFm); float32 float32_pol(float32 rFn, float32 rFm); -static float32 float32_rsf(float32 rFn, float32 rFm) +static float32 float32_rsf(struct roundingData *roundData, float32 rFn, float32 rFm) { - return float32_sub(rFm, rFn); + return float32_sub(roundData, rFm, rFn); } -static float32 float32_rdv(float32 rFn, float32 rFm) +static float32 float32_rdv(struct roundingData *roundData, float32 rFn, float32 rFm) { - return float32_div(rFm, rFn); + return float32_div(roundData, rFm, rFn); } -static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = { +static float32 (*const dyadic_single[16])(struct roundingData *, float32 rFn, float32 rFm) = { [ADF_CODE >> 20] = float32_add, [MUF_CODE >> 20] = float32_mul, [SUF_CODE >> 20] = float32_sub, @@ -60,22 +60,22 @@ static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = { [FRD_CODE >> 20] = float32_rdv, }; -static float32 float32_mvf(float32 rFm) +static float32 float32_mvf(struct roundingData *roundData, float32 rFm) { return rFm; } -static float32 float32_mnf(float32 rFm) +static float32 float32_mnf(struct roundingData *roundData, float32 rFm) { return rFm ^ 0x80000000; } -static float32 float32_abs(float32 rFm) +static float32 float32_abs(struct roundingData *roundData, float32 rFm) { return rFm & 0x7fffffff; } -static float32 (*const monadic_single[16])(float32 rFm) = { +static float32 (*const monadic_single[16])(struct roundingData*, float32 rFm) = { [MVF_CODE >> 20] = float32_mvf, [MNF_CODE >> 20] = float32_mnf, [ABS_CODE >> 20] = float32_abs, @@ -85,7 +85,7 @@ static float32 (*const monadic_single[16])(float32 rFm) = { [NRM_CODE >> 20] = float32_mvf, }; -unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd) +unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd) { FPA11 *fpa11 = GET_FPA11(); float32 rFm; @@ -108,13 +108,13 @@ unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd) if (fpa11->fType[Fn] == typeSingle && dyadic_single[opc_mask_shift]) { rFn = fpa11->fpreg[Fn].fSingle; - rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm); + rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm); } else { return 0; } } else { if (monadic_single[opc_mask_shift]) { - rFd->fSingle = monadic_single[opc_mask_shift](rFm); + rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm); } else { return 0; } diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c index e038dd3be9b3..8b75a6e7cb3a 100644 --- a/arch/arm/nwfpe/softfloat.c +++ b/arch/arm/nwfpe/softfloat.c @@ -34,16 +34,6 @@ this code that are retained. //#include "milieu.h" //#include "softfloat.h" -/* -------------------------------------------------------------------------------- -Floating-point rounding mode, extended double-precision rounding precision, -and exception flags. -------------------------------------------------------------------------------- -*/ -int8 float_rounding_mode = float_round_nearest_even; -int8 floatx80_rounding_precision = 80; -int8 float_exception_flags; - /* ------------------------------------------------------------------------------- Primitive arithmetic functions, including multi-word arithmetic, and @@ -77,14 +67,14 @@ input is too large, however, the invalid exception is raised and the largest positive or negative integer is returned. ------------------------------------------------------------------------------- */ -static int32 roundAndPackInt32( flag zSign, bits64 absZ ) +static int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits64 absZ ) { int8 roundingMode; flag roundNearestEven; int8 roundIncrement, roundBits; int32 z; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; if ( ! roundNearestEven ) { @@ -107,10 +97,10 @@ static int32 roundAndPackInt32( flag zSign, bits64 absZ ) z = absZ; if ( zSign ) z = - z; if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - float_exception_flags |= float_flag_invalid; + roundData->exception |= float_flag_invalid; return zSign ? 0x80000000 : 0x7FFFFFFF; } - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( roundBits ) roundData->exception |= float_flag_inexact; return z; } @@ -224,14 +214,14 @@ The handling of underflow and overflow follows the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) +static float32 roundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) { int8 roundingMode; flag roundNearestEven; int8 roundIncrement, roundBits; flag isTiny; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; if ( ! roundNearestEven ) { @@ -254,7 +244,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) || ( ( zExp == 0xFD ) && ( (sbits32) ( zSig + roundIncrement ) < 0 ) ) ) { - float_raise( float_flag_overflow | float_flag_inexact ); + roundData->exception |= float_flag_overflow | float_flag_inexact; return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 ); } if ( zExp < 0 ) { @@ -265,10 +255,10 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) shift32RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x7F; - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); + if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; } } - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( roundBits ) roundData->exception |= float_flag_inexact; zSig = ( zSig + roundIncrement )>>7; zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); if ( zSig == 0 ) zExp = 0; @@ -287,12 +277,12 @@ point exponent. ------------------------------------------------------------------------------- */ static float32 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) + normalizeRoundAndPackFloat32( struct roundingData *roundData, flag zSign, int16 zExp, bits32 zSig ) { int8 shiftCount; shiftCount = countLeadingZeros32( zSig ) - 1; - return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<mode; roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x200; if ( ! roundNearestEven ) { @@ -427,7 +417,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) ) { //register int lr = __builtin_return_address(0); //printk("roundAndPackFloat64 called from 0x%08x\n",lr); - float_raise( float_flag_overflow | float_flag_inexact ); + roundData->exception |= float_flag_overflow | float_flag_inexact; return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 ); } if ( zExp < 0 ) { @@ -438,10 +428,10 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) shift64RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x3FF; - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); + if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; } } - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( roundBits ) roundData->exception |= float_flag_inexact; zSig = ( zSig + roundIncrement )>>10; zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); if ( zSig == 0 ) zExp = 0; @@ -460,12 +450,12 @@ point exponent. ------------------------------------------------------------------------------- */ static float64 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) + normalizeRoundAndPackFloat64( struct roundingData *roundData, flag zSign, int16 zExp, bits64 zSig ) { int8 shiftCount; shiftCount = countLeadingZeros64( zSig ) - 1; - return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<mode; + roundingPrecision = roundData->precision; roundNearestEven = ( roundingMode == float_round_nearest_even ); if ( roundingPrecision == 80 ) goto precision80; if ( roundingPrecision == 64 ) { @@ -623,8 +614,8 @@ static floatx80 shift64RightJamming( zSig0, 1 - zExp, &zSig0 ); zExp = 0; roundBits = zSig0 & roundMask; - if ( isTiny && roundBits ) float_raise( float_flag_underflow ); - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( isTiny && roundBits ) roundData->exception |= float_flag_underflow; + if ( roundBits ) roundData->exception |= float_flag_inexact; zSig0 += roundIncrement; if ( (sbits64) zSig0 < 0 ) zExp = 1; roundIncrement = roundMask + 1; @@ -635,7 +626,7 @@ static floatx80 return packFloatx80( zSign, zExp, zSig0 ); } } - if ( roundBits ) float_exception_flags |= float_flag_inexact; + if ( roundBits ) roundData->exception |= float_flag_inexact; zSig0 += roundIncrement; if ( zSig0 < roundIncrement ) { ++zExp; @@ -672,7 +663,7 @@ static floatx80 ) { roundMask = 0; overflow: - float_raise( float_flag_overflow | float_flag_inexact ); + roundData->exception |= float_flag_overflow | float_flag_inexact; if ( ( roundingMode == float_round_to_zero ) || ( zSign && ( roundingMode == float_round_up ) ) || ( ! zSign && ( roundingMode == float_round_down ) ) @@ -689,8 +680,8 @@ static floatx80 || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) ); shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); zExp = 0; - if ( isTiny && zSig1 ) float_raise( float_flag_underflow ); - if ( zSig1 ) float_exception_flags |= float_flag_inexact; + if ( isTiny && zSig1 ) roundData->exception |= float_flag_underflow; + if ( zSig1 ) roundData->exception |= float_flag_inexact; if ( roundNearestEven ) { increment = ( (sbits64) zSig1 < 0 ); } @@ -710,7 +701,7 @@ static floatx80 return packFloatx80( zSign, zExp, zSig0 ); } } - if ( zSig1 ) float_exception_flags |= float_flag_inexact; + if ( zSig1 ) roundData->exception |= float_flag_inexact; if ( increment ) { ++zSig0; if ( zSig0 == 0 ) { @@ -740,7 +731,7 @@ normalized. */ static floatx80 normalizeRoundAndPackFloatx80( - int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 + struct roundingData *roundData, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) { int8 shiftCount; @@ -754,7 +745,7 @@ static floatx80 shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); zExp -= shiftCount; return - roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 ); + roundAndPackFloatx80( roundData, zSign, zExp, zSig0, zSig1 ); } @@ -767,14 +758,14 @@ the single-precision floating-point format. The conversion is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 int32_to_float32( int32 a ) +float32 int32_to_float32(struct roundingData *roundData, int32 a) { flag zSign; if ( a == 0 ) return 0; if ( a == 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); zSign = ( a < 0 ); - return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a ); + return normalizeRoundAndPackFloat32( roundData, zSign, 0x9C, zSign ? - a : a ); } @@ -840,7 +831,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the largest integer with the same sign as `a' is returned. ------------------------------------------------------------------------------- */ -int32 float32_to_int32( float32 a ) +int32 float32_to_int32( struct roundingData *roundData, float32 a ) { flag aSign; int16 aExp, shiftCount; @@ -856,7 +847,7 @@ int32 float32_to_int32( float32 a ) zSig = aSig; zSig <<= 32; if ( 0 < shiftCount ) shift64RightJamming( zSig, shiftCount, &zSig ); - return roundAndPackInt32( aSign, zSig ); + return roundAndPackInt32( roundData, aSign, zSig ); } @@ -889,13 +880,13 @@ int32 float32_to_int32_round_to_zero( float32 a ) return 0x80000000; } else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; + if ( aExp | aSig ) float_raise( float_flag_inexact ); return 0; } aSig = ( aSig | 0x00800000 )<<8; z = aSig>>( - shiftCount ); if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_exception_flags |= float_flag_inexact; + float_raise( float_flag_inexact ); } return aSign ? - z : z; @@ -973,7 +964,7 @@ operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_round_to_int( float32 a ) +float32 float32_round_to_int( struct roundingData *roundData, float32 a ) { flag aSign; int16 aExp; @@ -988,11 +979,12 @@ float32 float32_round_to_int( float32 a ) } return a; } + roundingMode = roundData->mode; if ( aExp <= 0x7E ) { if ( (bits32) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; + roundData->exception |= float_flag_inexact; aSign = extractFloat32Sign( a ); - switch ( float_rounding_mode ) { + switch ( roundingMode ) { case float_round_nearest_even: if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { return packFloat32( aSign, 0x7F, 0 ); @@ -1009,7 +1001,6 @@ float32 float32_round_to_int( float32 a ) lastBitMask <<= 0x96 - aExp; roundBitsMask = lastBitMask - 1; z = a; - roundingMode = float_rounding_mode; if ( roundingMode == float_round_nearest_even ) { z += lastBitMask>>1; if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; @@ -1020,7 +1011,7 @@ float32 float32_round_to_int( float32 a ) } } z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; + if ( z != a ) roundData->exception |= float_flag_inexact; return z; } @@ -1034,7 +1025,7 @@ addition is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) +static float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) { int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; @@ -1093,7 +1084,7 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) ++zExp; } roundAndPack: - return roundAndPackFloat32( zSign, zExp, zSig ); + return roundAndPackFloat32( roundData, zSign, zExp, zSig ); } @@ -1106,7 +1097,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) +static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign ) { int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; @@ -1123,7 +1114,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) if ( expDiff < 0 ) goto bExpBigger; if ( aExp == 0xFF ) { if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } if ( aExp == 0 ) { @@ -1132,7 +1123,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) } if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; - return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); + return packFloat32( roundData->mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0xFF ) { if ( bSig ) return propagateFloat32NaN( a, b ); @@ -1169,7 +1160,7 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) zExp = aExp; normalizeRoundAndPack: --zExp; - return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); + return normalizeRoundAndPackFloat32( roundData, zSign, zExp, zSig ); } @@ -1180,17 +1171,17 @@ and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_add( float32 a, float32 b ) +float32 float32_add( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign; aSign = extractFloat32Sign( a ); bSign = extractFloat32Sign( b ); if ( aSign == bSign ) { - return addFloat32Sigs( a, b, aSign ); + return addFloat32Sigs( roundData, a, b, aSign ); } else { - return subFloat32Sigs( a, b, aSign ); + return subFloat32Sigs( roundData, a, b, aSign ); } } @@ -1202,17 +1193,17 @@ Returns the result of subtracting the single-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_sub( float32 a, float32 b ) +float32 float32_sub( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign; aSign = extractFloat32Sign( a ); bSign = extractFloat32Sign( b ); if ( aSign == bSign ) { - return subFloat32Sigs( a, b, aSign ); + return subFloat32Sigs( roundData, a, b, aSign ); } else { - return addFloat32Sigs( a, b, aSign ); + return addFloat32Sigs( roundData, a, b, aSign ); } } @@ -1224,7 +1215,7 @@ Returns the result of multiplying the single-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_mul( float32 a, float32 b ) +float32 float32_mul( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -1244,7 +1235,7 @@ float32 float32_mul( float32 a, float32 b ) return propagateFloat32NaN( a, b ); } if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } return packFloat32( zSign, 0xFF, 0 ); @@ -1252,7 +1243,7 @@ float32 float32_mul( float32 a, float32 b ) if ( bExp == 0xFF ) { if ( bSig ) return propagateFloat32NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } return packFloat32( zSign, 0xFF, 0 ); @@ -1274,7 +1265,7 @@ float32 float32_mul( float32 a, float32 b ) zSig <<= 1; --zExp; } - return roundAndPackFloat32( zSign, zExp, zSig ); + return roundAndPackFloat32( roundData, zSign, zExp, zSig ); } @@ -1285,7 +1276,7 @@ by the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_div( float32 a, float32 b ) +float32 float32_div( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -1302,7 +1293,7 @@ float32 float32_div( float32 a, float32 b ) if ( aSig ) return propagateFloat32NaN( a, b ); if ( bExp == 0xFF ) { if ( bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } return packFloat32( zSign, 0xFF, 0 ); @@ -1314,10 +1305,10 @@ float32 float32_div( float32 a, float32 b ) if ( bExp == 0 ) { if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } - float_raise( float_flag_divbyzero ); + roundData->exception |= float_flag_divbyzero; return packFloat32( zSign, 0xFF, 0 ); } normalizeFloat32Subnormal( bSig, &bExp, &bSig ); @@ -1341,7 +1332,7 @@ float32 float32_div( float32 a, float32 b ) if ( ( zSig & 0x3F ) == 0 ) { zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 ); } - return roundAndPackFloat32( zSign, zExp, zSig ); + return roundAndPackFloat32( roundData, zSign, zExp, zSig ); } @@ -1352,7 +1343,7 @@ with respect to the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_rem( float32 a, float32 b ) +float32 float32_rem( struct roundingData *roundData, float32 a, float32 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, expDiff; @@ -1372,7 +1363,7 @@ float32 float32_rem( float32 a, float32 b ) if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { return propagateFloat32NaN( a, b ); } - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } if ( bExp == 0xFF ) { @@ -1381,7 +1372,7 @@ float32 float32_rem( float32 a, float32 b ) } if ( bExp == 0 ) { if ( bSig == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } normalizeFloat32Subnormal( bSig, &bExp, &bSig ); @@ -1444,7 +1435,7 @@ float32 float32_rem( float32 a, float32 b ) } zSign = ( (sbits32) aSig < 0 ); if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); + return normalizeRoundAndPackFloat32( roundData, aSign ^ zSign, bExp, aSig ); } @@ -1455,7 +1446,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float32 float32_sqrt( float32 a ) +float32 float32_sqrt( struct roundingData *roundData, float32 a ) { flag aSign; int16 aExp, zExp; @@ -1468,12 +1459,12 @@ float32 float32_sqrt( float32 a ) if ( aExp == 0xFF ) { if ( aSig ) return propagateFloat32NaN( a, 0 ); if ( ! aSign ) return a; - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } if ( aSign ) { if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float32_default_nan; } if ( aExp == 0 ) { @@ -1499,7 +1490,7 @@ float32 float32_sqrt( float32 a ) } } shift32RightJamming( zSig, 1, &zSig ); - return roundAndPackFloat32( 0, zExp, zSig ); + return roundAndPackFloat32( roundData, 0, zExp, zSig ); } @@ -1661,7 +1652,7 @@ positive integer is returned. Otherwise, if the conversion overflows, the largest integer with the same sign as `a' is returned. ------------------------------------------------------------------------------- */ -int32 float64_to_int32( float64 a ) +int32 float64_to_int32( struct roundingData *roundData, float64 a ) { flag aSign; int16 aExp, shiftCount; @@ -1674,7 +1665,7 @@ int32 float64_to_int32( float64 a ) if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); shiftCount = 0x42C - aExp; if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); + return roundAndPackInt32( roundData, aSign, aSig ); } @@ -1705,7 +1696,7 @@ int32 float64_to_int32_round_to_zero( float64 a ) goto invalid; } else if ( 52 < shiftCount ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + if ( aExp || aSig ) float_raise( float_flag_inexact ); return 0; } aSig |= LIT64( 0x0010000000000000 ); @@ -1715,11 +1706,11 @@ int32 float64_to_int32_round_to_zero( float64 a ) if ( aSign ) z = - z; if ( ( z < 0 ) ^ aSign ) { invalid: - float_exception_flags |= float_flag_invalid; + float_raise( float_flag_invalid ); return aSign ? 0x80000000 : 0x7FFFFFFF; } if ( ( aSig<exception |= float_flag_inexact; aSign = extractFloat64Sign( a ); - switch ( float_rounding_mode ) { + switch ( roundData->mode ) { case float_round_nearest_even: if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { return packFloat64( aSign, 0x3FF, 0 ); @@ -1909,7 +1900,7 @@ float64 float64_round_to_int( float64 a ) lastBitMask <<= 0x433 - aExp; roundBitsMask = lastBitMask - 1; z = a; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; if ( roundingMode == float_round_nearest_even ) { z += lastBitMask>>1; if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; @@ -1920,7 +1911,7 @@ float64 float64_round_to_int( float64 a ) } } z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; + if ( z != a ) roundData->exception |= float_flag_inexact; return z; } @@ -1934,7 +1925,7 @@ addition is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) +static float64 addFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) { int16 aExp, bExp, zExp; bits64 aSig, bSig, zSig; @@ -1993,7 +1984,7 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) ++zExp; } roundAndPack: - return roundAndPackFloat64( zSign, zExp, zSig ); + return roundAndPackFloat64( roundData, zSign, zExp, zSig ); } @@ -2006,7 +1997,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) +static float64 subFloat64Sigs( struct roundingData *roundData, float64 a, float64 b, flag zSign ) { int16 aExp, bExp, zExp; bits64 aSig, bSig, zSig; @@ -2023,7 +2014,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) if ( expDiff < 0 ) goto bExpBigger; if ( aExp == 0x7FF ) { if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } if ( aExp == 0 ) { @@ -2032,7 +2023,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) } if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; - return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); + return packFloat64( roundData->mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0x7FF ) { if ( bSig ) return propagateFloat64NaN( a, b ); @@ -2069,7 +2060,7 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) zExp = aExp; normalizeRoundAndPack: --zExp; - return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); + return normalizeRoundAndPackFloat64( roundData, zSign, zExp, zSig ); } @@ -2080,17 +2071,17 @@ and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_add( float64 a, float64 b ) +float64 float64_add( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign; aSign = extractFloat64Sign( a ); bSign = extractFloat64Sign( b ); if ( aSign == bSign ) { - return addFloat64Sigs( a, b, aSign ); + return addFloat64Sigs( roundData, a, b, aSign ); } else { - return subFloat64Sigs( a, b, aSign ); + return subFloat64Sigs( roundData, a, b, aSign ); } } @@ -2102,17 +2093,17 @@ Returns the result of subtracting the double-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_sub( float64 a, float64 b ) +float64 float64_sub( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign; aSign = extractFloat64Sign( a ); bSign = extractFloat64Sign( b ); if ( aSign == bSign ) { - return subFloat64Sigs( a, b, aSign ); + return subFloat64Sigs( roundData, a, b, aSign ); } else { - return addFloat64Sigs( a, b, aSign ); + return addFloat64Sigs( roundData, a, b, aSign ); } } @@ -2124,7 +2115,7 @@ Returns the result of multiplying the double-precision floating-point values for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_mul( float64 a, float64 b ) +float64 float64_mul( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -2142,7 +2133,7 @@ float64 float64_mul( float64 a, float64 b ) return propagateFloat64NaN( a, b ); } if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } return packFloat64( zSign, 0x7FF, 0 ); @@ -2150,7 +2141,7 @@ float64 float64_mul( float64 a, float64 b ) if ( bExp == 0x7FF ) { if ( bSig ) return propagateFloat64NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } return packFloat64( zSign, 0x7FF, 0 ); @@ -2172,7 +2163,7 @@ float64 float64_mul( float64 a, float64 b ) zSig0 <<= 1; --zExp; } - return roundAndPackFloat64( zSign, zExp, zSig0 ); + return roundAndPackFloat64( roundData, zSign, zExp, zSig0 ); } @@ -2183,7 +2174,7 @@ by the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_div( float64 a, float64 b ) +float64 float64_div( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, zExp; @@ -2202,7 +2193,7 @@ float64 float64_div( float64 a, float64 b ) if ( aSig ) return propagateFloat64NaN( a, b ); if ( bExp == 0x7FF ) { if ( bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } return packFloat64( zSign, 0x7FF, 0 ); @@ -2214,10 +2205,10 @@ float64 float64_div( float64 a, float64 b ) if ( bExp == 0 ) { if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } - float_raise( float_flag_divbyzero ); + roundData->exception |= float_flag_divbyzero; return packFloat64( zSign, 0x7FF, 0 ); } normalizeFloat64Subnormal( bSig, &bExp, &bSig ); @@ -2243,7 +2234,7 @@ float64 float64_div( float64 a, float64 b ) } zSig |= ( rem1 != 0 ); } - return roundAndPackFloat64( zSign, zExp, zSig ); + return roundAndPackFloat64( roundData, zSign, zExp, zSig ); } @@ -2254,7 +2245,7 @@ with respect to the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_rem( float64 a, float64 b ) +float64 float64_rem( struct roundingData *roundData, float64 a, float64 b ) { flag aSign, bSign, zSign; int16 aExp, bExp, expDiff; @@ -2272,7 +2263,7 @@ float64 float64_rem( float64 a, float64 b ) if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { return propagateFloat64NaN( a, b ); } - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } if ( bExp == 0x7FF ) { @@ -2281,7 +2272,7 @@ float64 float64_rem( float64 a, float64 b ) } if ( bExp == 0 ) { if ( bSig == 0 ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } normalizeFloat64Subnormal( bSig, &bExp, &bSig ); @@ -2329,7 +2320,7 @@ float64 float64_rem( float64 a, float64 b ) } zSign = ( (sbits64) aSig < 0 ); if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); + return normalizeRoundAndPackFloat64( roundData, aSign ^ zSign, bExp, aSig ); } @@ -2340,7 +2331,7 @@ The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -float64 float64_sqrt( float64 a ) +float64 float64_sqrt( struct roundingData *roundData, float64 a ) { flag aSign; int16 aExp, zExp; @@ -2354,12 +2345,12 @@ float64 float64_sqrt( float64 a ) if ( aExp == 0x7FF ) { if ( aSig ) return propagateFloat64NaN( a, a ); if ( ! aSign ) return a; - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } if ( aSign ) { if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return float64_default_nan; } if ( aExp == 0 ) { @@ -2390,7 +2381,7 @@ float64 float64_sqrt( float64 a ) } } shift64RightJamming( zSig, 1, &zSig ); - return roundAndPackFloat64( 0, zExp, zSig ); + return roundAndPackFloat64( roundData, 0, zExp, zSig ); } @@ -2554,7 +2545,7 @@ largest positive integer is returned. Otherwise, if the conversion overflows, the largest integer with the same sign as `a' is returned. ------------------------------------------------------------------------------- */ -int32 floatx80_to_int32( floatx80 a ) +int32 floatx80_to_int32( struct roundingData *roundData, floatx80 a ) { flag aSign; int32 aExp, shiftCount; @@ -2567,7 +2558,7 @@ int32 floatx80_to_int32( floatx80 a ) shiftCount = 0x4037 - aExp; if ( shiftCount <= 0 ) shiftCount = 1; shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); + return roundAndPackInt32( roundData, aSign, aSig ); } @@ -2598,7 +2589,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a ) goto invalid; } else if ( 63 < shiftCount ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + if ( aExp || aSig ) float_raise( float_flag_inexact ); return 0; } savedASig = aSig; @@ -2607,11 +2598,11 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a ) if ( aSign ) z = - z; if ( ( z < 0 ) ^ aSign ) { invalid: - float_exception_flags |= float_flag_invalid; + float_raise( float_flag_invalid ); return aSign ? 0x80000000 : 0x7FFFFFFF; } if ( ( aSig<exception |= float_flag_inexact; aSign = extractFloatx80Sign( a ); - switch ( float_rounding_mode ) { + switch ( roundData->mode ) { case float_round_nearest_even: if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { @@ -2729,7 +2720,7 @@ floatx80 floatx80_round_to_int( floatx80 a ) lastBitMask <<= 0x403E - aExp; roundBitsMask = lastBitMask - 1; z = a; - roundingMode = float_rounding_mode; + roundingMode = roundData->mode; if ( roundingMode == float_round_nearest_even ) { z.low += lastBitMask>>1; if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; @@ -2744,7 +2735,7 @@ floatx80 floatx80_round_to_int( floatx80 a ) ++z.high; z.low = LIT64( 0x8000000000000000 ); } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; + if ( z.low != a.low ) roundData->exception |= float_flag_inexact; return z; } @@ -2758,7 +2749,7 @@ The addition is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +static floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) { int32 aExp, bExp, zExp; bits64 aSig, bSig, zSig0, zSig1; @@ -2814,7 +2805,7 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) roundAndPack: return roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + roundData, zSign, zExp, zSig0, zSig1 ); } @@ -2827,7 +2818,7 @@ result is a NaN. The subtraction is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +static floatx80 subFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign ) { int32 aExp, bExp, zExp; bits64 aSig, bSig, zSig0, zSig1; @@ -2845,7 +2836,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) if ( (bits64) ( ( aSig | bSig )<<1 ) ) { return propagateFloatx80NaN( a, b ); } - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -2857,7 +2848,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) zSig1 = 0; if ( bSig < aSig ) goto aBigger; if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); + return packFloatx80( roundData->mode == float_round_down, 0, 0 ); bExpBigger: if ( bExp == 0x7FFF ) { if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); @@ -2883,7 +2874,7 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) normalizeRoundAndPack: return normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + roundData, zSign, zExp, zSig0, zSig1 ); } @@ -2894,17 +2885,17 @@ values `a' and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_add( floatx80 a, floatx80 b ) +floatx80 floatx80_add( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign; aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); + return addFloatx80Sigs( roundData, a, b, aSign ); } else { - return subFloatx80Sigs( a, b, aSign ); + return subFloatx80Sigs( roundData, a, b, aSign ); } } @@ -2916,17 +2907,17 @@ point values `a' and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_sub( floatx80 a, floatx80 b ) +floatx80 floatx80_sub( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign; aSign = extractFloatx80Sign( a ); bSign = extractFloatx80Sign( b ); if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); + return subFloatx80Sigs( roundData, a, b, aSign ); } else { - return addFloatx80Sigs( a, b, aSign ); + return addFloatx80Sigs( roundData, a, b, aSign ); } } @@ -2938,7 +2929,7 @@ point values `a' and `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_mul( floatx80 a, floatx80 b ) +floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; int32 aExp, bExp, zExp; @@ -2964,7 +2955,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b ) if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); if ( ( aExp | aSig ) == 0 ) { invalid: - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -2987,7 +2978,7 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b ) } return roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + roundData, zSign, zExp, zSig0, zSig1 ); } @@ -2998,7 +2989,7 @@ value `a' by the corresponding value `b'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_div( floatx80 a, floatx80 b ) +floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; int32 aExp, bExp, zExp; @@ -3029,12 +3020,12 @@ floatx80 floatx80_div( floatx80 a, floatx80 b ) if ( bSig == 0 ) { if ( ( aExp | aSig ) == 0 ) { invalid: - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; } - float_raise( float_flag_divbyzero ); + roundData->exception |= float_flag_divbyzero; return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); @@ -3068,7 +3059,7 @@ floatx80 floatx80_div( floatx80 a, floatx80 b ) } return roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + roundData, zSign, zExp, zSig0, zSig1 ); } @@ -3079,7 +3070,7 @@ Returns the remainder of the extended double-precision floating-point value according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_rem( floatx80 a, floatx80 b ) +floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b ) { flag aSign, bSign, zSign; int32 aExp, bExp, expDiff; @@ -3107,7 +3098,7 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b ) if ( bExp == 0 ) { if ( bSig == 0 ) { invalid: - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -3164,9 +3155,10 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b ) aSig1 = alternateASig1; zSign = ! zSign; } + return normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); + roundData, zSign, bExp + expDiff, aSig0, aSig1 ); } @@ -3177,7 +3169,7 @@ value `a'. The operation is performed according to the IEC/IEEE Standard for Binary Floating-point Arithmetic. ------------------------------------------------------------------------------- */ -floatx80 floatx80_sqrt( floatx80 a ) +floatx80 floatx80_sqrt( struct roundingData *roundData, floatx80 a ) { flag aSign; int32 aExp, zExp; @@ -3197,7 +3189,7 @@ floatx80 floatx80_sqrt( floatx80 a ) if ( aSign ) { if ( ( aExp | aSig0 ) == 0 ) return a; invalid: - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; z.low = floatx80_default_nan_low; z.high = floatx80_default_nan_high; return z; @@ -3242,7 +3234,7 @@ floatx80 floatx80_sqrt( floatx80 a ) } return roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); + roundData, 0, zExp, zSig0, zSig1 ); } @@ -3264,7 +3256,7 @@ flag floatx80_eq( floatx80 a, floatx80 b ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; } return 0; } @@ -3294,7 +3286,7 @@ flag floatx80_le( floatx80 a, floatx80 b ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return 0; } aSign = extractFloatx80Sign( a ); @@ -3328,7 +3320,7 @@ flag floatx80_lt( floatx80 a, floatx80 b ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return 0; } aSign = extractFloatx80Sign( a ); @@ -3361,7 +3353,7 @@ flag floatx80_eq_signaling( floatx80 a, floatx80 b ) || ( ( extractFloatx80Exp( b ) == 0x7FFF ) && (bits64) ( extractFloatx80Frac( b )<<1 ) ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; return 0; } return @@ -3392,7 +3384,7 @@ flag floatx80_le_quiet( floatx80 a, floatx80 b ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; } return 0; } @@ -3429,7 +3421,7 @@ flag floatx80_lt_quiet( floatx80 a, floatx80 b ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); + roundData->exception |= float_flag_invalid; } return 0; } diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h index 1e1743173899..1c8799b9ee4d 100644 --- a/arch/arm/nwfpe/softfloat.h +++ b/arch/arm/nwfpe/softfloat.h @@ -74,7 +74,7 @@ enum { Software IEC/IEEE floating-point rounding mode. ------------------------------------------------------------------------------- */ -extern signed char float_rounding_mode; +//extern int8 float_rounding_mode; enum { float_round_nearest_even = 0, float_round_to_zero = 1, @@ -86,7 +86,6 @@ enum { ------------------------------------------------------------------------------- Software IEC/IEEE floating-point exception flags. ------------------------------------------------------------------------------- -extern signed char float_exception_flags; enum { float_flag_inexact = 1, float_flag_underflow = 2, @@ -99,7 +98,6 @@ ScottB: November 4, 1998 Changed the enumeration to match the bit order in the FPA11. */ -extern signed char float_exception_flags; enum { float_flag_invalid = 1, float_flag_divbyzero = 2, @@ -121,7 +119,7 @@ void float_raise( signed char ); Software IEC/IEEE integer-to-floating-point conversion routines. ------------------------------------------------------------------------------- */ -float32 int32_to_float32( signed int ); +float32 int32_to_float32( struct roundingData *, signed int ); float64 int32_to_float64( signed int ); #ifdef FLOATX80 floatx80 int32_to_floatx80( signed int ); @@ -132,7 +130,7 @@ floatx80 int32_to_floatx80( signed int ); Software IEC/IEEE single-precision conversion routines. ------------------------------------------------------------------------------- */ -signed int float32_to_int32( float32 ); +signed int float32_to_int32( struct roundingData *, float32 ); signed int float32_to_int32_round_to_zero( float32 ); float64 float32_to_float64( float32 ); #ifdef FLOATX80 @@ -144,13 +142,13 @@ floatx80 float32_to_floatx80( float32 ); Software IEC/IEEE single-precision operations. ------------------------------------------------------------------------------- */ -float32 float32_round_to_int( float32 ); -float32 float32_add( float32, float32 ); -float32 float32_sub( float32, float32 ); -float32 float32_mul( float32, float32 ); -float32 float32_div( float32, float32 ); -float32 float32_rem( float32, float32 ); -float32 float32_sqrt( float32 ); +float32 float32_round_to_int( struct roundingData*, float32 ); +float32 float32_add( struct roundingData *, float32, float32 ); +float32 float32_sub( struct roundingData *, float32, float32 ); +float32 float32_mul( struct roundingData *, float32, float32 ); +float32 float32_div( struct roundingData *, float32, float32 ); +float32 float32_rem( struct roundingData *, float32, float32 ); +float32 float32_sqrt( struct roundingData*, float32 ); char float32_eq( float32, float32 ); char float32_le( float32, float32 ); char float32_lt( float32, float32 ); @@ -164,9 +162,9 @@ char float32_is_signaling_nan( float32 ); Software IEC/IEEE double-precision conversion routines. ------------------------------------------------------------------------------- */ -signed int float64_to_int32( float64 ); +signed int float64_to_int32( struct roundingData *, float64 ); signed int float64_to_int32_round_to_zero( float64 ); -float32 float64_to_float32( float64 ); +float32 float64_to_float32( struct roundingData *, float64 ); #ifdef FLOATX80 floatx80 float64_to_floatx80( float64 ); #endif @@ -176,13 +174,13 @@ floatx80 float64_to_floatx80( float64 ); Software IEC/IEEE double-precision operations. ------------------------------------------------------------------------------- */ -float64 float64_round_to_int( float64 ); -float64 float64_add( float64, float64 ); -float64 float64_sub( float64, float64 ); -float64 float64_mul( float64, float64 ); -float64 float64_div( float64, float64 ); -float64 float64_rem( float64, float64 ); -float64 float64_sqrt( float64 ); +float64 float64_round_to_int( struct roundingData *, float64 ); +float64 float64_add( struct roundingData *, float64, float64 ); +float64 float64_sub( struct roundingData *, float64, float64 ); +float64 float64_mul( struct roundingData *, float64, float64 ); +float64 float64_div( struct roundingData *, float64, float64 ); +float64 float64_rem( struct roundingData *, float64, float64 ); +float64 float64_sqrt( struct roundingData *, float64 ); char float64_eq( float64, float64 ); char float64_le( float64, float64 ); char float64_lt( float64, float64 ); @@ -198,31 +196,23 @@ char float64_is_signaling_nan( float64 ); Software IEC/IEEE extended double-precision conversion routines. ------------------------------------------------------------------------------- */ -signed int floatx80_to_int32( floatx80 ); +signed int floatx80_to_int32( struct roundingData *, floatx80 ); signed int floatx80_to_int32_round_to_zero( floatx80 ); -float32 floatx80_to_float32( floatx80 ); -float64 floatx80_to_float64( floatx80 ); - -/* -------------------------------------------------------------------------------- -Software IEC/IEEE extended double-precision rounding precision. Valid -values are 32, 64, and 80. -------------------------------------------------------------------------------- -*/ -extern signed char floatx80_rounding_precision; +float32 floatx80_to_float32( struct roundingData *, floatx80 ); +float64 floatx80_to_float64( struct roundingData *, floatx80 ); /* ------------------------------------------------------------------------------- Software IEC/IEEE extended double-precision operations. ------------------------------------------------------------------------------- */ -floatx80 floatx80_round_to_int( floatx80 ); -floatx80 floatx80_add( floatx80, floatx80 ); -floatx80 floatx80_sub( floatx80, floatx80 ); -floatx80 floatx80_mul( floatx80, floatx80 ); -floatx80 floatx80_div( floatx80, floatx80 ); -floatx80 floatx80_rem( floatx80, floatx80 ); -floatx80 floatx80_sqrt( floatx80 ); +floatx80 floatx80_round_to_int( struct roundingData *, floatx80 ); +floatx80 floatx80_add( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_sub( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_mul( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_div( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_rem( struct roundingData *, floatx80, floatx80 ); +floatx80 floatx80_sqrt( struct roundingData *, floatx80 ); char floatx80_eq( floatx80, floatx80 ); char floatx80_le( floatx80, floatx80 ); char floatx80_lt( floatx80, floatx80 ); -- cgit v1.2.3 From 975ad141eecccb24fc8db1e0f4a08f5580f4a9a9 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Wed, 3 Aug 2005 19:49:17 +0100 Subject: [PATCH] ARM: 2839/1: Remove XScale cache and TLB locking code Patch from Deepak Saxena The XScale locking code is not something that has been validated on 2.6 and needs to be replaced with a more generic API to use with other ARMs that support locking features. Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mm/proc-xscale.S | 136 ---------------------------------------------- 1 file changed, 136 deletions(-) diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 2d977b4eeeab..b88de2700146 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -370,142 +370,6 @@ ENTRY(cpu_xscale_dcache_clean_area) bhi 1b mov pc, lr -/* ================================ CACHE LOCKING============================ - * - * The XScale MicroArchitecture implements support for locking entries into - * the data and instruction cache. The following functions implement the core - * low level instructions needed to accomplish the locking. The developer's - * manual states that the code that performs the locking must be in non-cached - * memory. To accomplish this, the code in xscale-cache-lock.c copies the - * following functions from the cache into a non-cached memory region that - * is allocated through consistent_alloc(). - * - */ - .align 5 -/* - * xscale_icache_lock - * - * r0: starting address to lock - * r1: end address to lock - */ -ENTRY(xscale_icache_lock) - -iLockLoop: - bic r0, r0, #CACHELINESIZE - 1 - mcr p15, 0, r0, c9, c1, 0 @ lock into cache - cmp r0, r1 @ are we done? - add r0, r0, #CACHELINESIZE @ advance to next cache line - bls iLockLoop - mov pc, lr - -/* - * xscale_icache_unlock - */ -ENTRY(xscale_icache_unlock) - mcr p15, 0, r0, c9, c1, 1 @ Unlock icache - mov pc, lr - -/* - * xscale_dcache_lock - * - * r0: starting address to lock - * r1: end address to lock - */ -ENTRY(xscale_dcache_lock) - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - mov r2, #1 - mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode - cpwait ip @ Wait for completion - - mrs r2, cpsr - orr r3, r2, #PSR_F_BIT | PSR_I_BIT -dLockLoop: - msr cpsr_c, r3 - mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty - mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line - msr cpsr_c, r2 - ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from - @ location [r0]. Post-increment - @ r3 to next cache line - cmp r0, r1 @ Are we done? - bls dLockLoop - - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - mov r2, #0 - mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode - cpwait_ret lr, ip - -/* - * xscale_dcache_unlock - */ -ENTRY(xscale_dcache_unlock) - mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer - mcr p15, 0, ip, c9, c2, 1 @ Unlock cache - mov pc, lr - -/* - * Needed to determine the length of the code that needs to be copied. - */ - .align 5 -ENTRY(xscale_cache_dummy) - mov pc, lr - -/* ================================ TLB LOCKING============================== - * - * The XScale MicroArchitecture implements support for locking entries into - * the Instruction and Data TLBs. The following functions provide the - * low level support for supporting these under Linux. xscale-lock.c - * implements some higher level management code. Most of the following - * is taken straight out of the Developer's Manual. - */ - -/* - * Lock I-TLB entry - * - * r0: Virtual address to translate and lock - */ - .align 5 -ENTRY(xscale_itlb_lock) - mrs r2, cpsr - orr r3, r2, #PSR_F_BIT | PSR_I_BIT - msr cpsr_c, r3 @ Disable interrupts - mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry - mcr p15, 0, r0, c10, c4, 0 @ Translate and lock - msr cpsr_c, r2 @ Restore interrupts - cpwait_ret lr, ip - -/* - * Lock D-TLB entry - * - * r0: Virtual address to translate and lock - */ - .align 5 -ENTRY(xscale_dtlb_lock) - mrs r2, cpsr - orr r3, r2, #PSR_F_BIT | PSR_I_BIT - msr cpsr_c, r3 @ Disable interrupts - mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry - mcr p15, 0, r0, c10, c8, 0 @ Translate and lock - msr cpsr_c, r2 @ Restore interrupts - cpwait_ret lr, ip - -/* - * Unlock all I-TLB entries - */ - .align 5 -ENTRY(xscale_itlb_unlock) - mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB - mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB - cpwait_ret lr, ip - -/* - * Unlock all D-TLB entries - */ -ENTRY(xscale_dtlb_unlock) - mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL - mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB - cpwait_ret lr, ip - /* =============================== PageTable ============================== */ #define PTE_CACHE_WRITE_ALLOCATE 0 -- cgit v1.2.3 From 858297509590ef4aa5690e30c2f5505077b4f369 Mon Sep 17 00:00:00 2001 From: Michael Burian Date: Wed, 3 Aug 2005 19:49:18 +0100 Subject: [PATCH] ARM: 2840/1: Add mach-types to Documentation/dontdiff Patch from Michael Burian This file is maintained by RMK's machine registry, it should not be patched. Signed-off-by: Michael Burian Signed-off-by: Russell King --- Documentation/dontdiff | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/dontdiff b/Documentation/dontdiff index b974cf595d01..96bea278bbf6 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -104,6 +104,7 @@ logo_*.c logo_*_clut224.c logo_*_mono.c lxdialog +mach-types mach-types.h make_times_h map -- cgit v1.2.3 From 7b1fbf292bb4c855ddae8add8c459e94684f7543 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 3 Aug 2005 19:53:25 +0100 Subject: [PATCH] ARM: 2841/1: Fix VFP +/-0 case for doubles addition Patch from Catalin Marinas The IEEE 754 standard specifies that the result of (x - x), where x is a valid number, should be -0 if the rounding mode is towards minus infinity or +0 otherwise. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/vfp/vfpdouble.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index b801cd66b6ea..9b367a65cb4d 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c @@ -770,6 +770,9 @@ vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn, if ((s64)m_sig < 0) { vdd->sign = vfp_sign_negate(vdd->sign); m_sig = -m_sig; + } else if (m_sig == 0) { + vdd->sign = (fpscr & FPSCR_RMODE_MASK) == + FPSCR_ROUND_MINUSINF ? 0x8000 : 0; } } else { m_sig += vdn->significand; -- cgit v1.2.3 From 8c741ed74d121dbc97c9fb7f9a66c768d4c547c4 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Wed, 3 Aug 2005 19:58:21 +0100 Subject: [PATCH] ARM: 2835/1: Add UPF_SKIP_TEST to IXP4xx serial ports Patch from Deepak Saxena This allows the serial driver autconf to work properly on all the IXP serial ports. W/o it we basically put the serial port in an unrecoverable state and lose console. Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/coyote-setup.c | 2 +- arch/arm/mach-ixp4xx/gtwx5715-setup.c | 2 +- arch/arm/mach-ixp4xx/ixdp425-setup.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 4ff4393ef0ea..7f58afb27e71 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -61,7 +61,7 @@ static struct plat_serial8250_port coyote_uart_data[] = { .mapbase = IXP4XX_UART2_BASE_PHYS, .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART2, - .flags = UPF_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 8ba1cd9406e7..65e356bd10d6 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c @@ -83,7 +83,7 @@ static struct plat_serial8250_port gtwx5715_uart_platform_data[] = { .mapbase = IXP4XX_UART2_BASE_PHYS, .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART2, - .flags = UPF_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index c2ba759e9946..4633470a6a37 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -82,7 +82,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = { .mapbase = IXP4XX_UART1_BASE_PHYS, .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART1, - .flags = UPF_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, @@ -91,7 +91,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = { .mapbase = IXP4XX_UART2_BASE_PHYS, .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, .irq = IRQ_IXP4XX_UART1, - .flags = UPF_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, .iotype = UPIO_MEM, .regshift = 2, .uartclk = IXP4XX_UART_XTAL, -- cgit v1.2.3 From 9bbd03758945858c9303f3258b418b94c4ffd735 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 3 Aug 2005 20:34:52 +0100 Subject: [PATCH] ARM: 2833/2: Remove support for WDIOF_MAGICCLOSE from sa1100-wdt Patch from Ian Campbell On PXA255 there is no way to disable the watchdog. Turning off OIER[E3] as suggested in the existing comment does not work. I posted a note to the ARM mailing list a little while ago asking for opinions from people using SA1100. There was one reponse from Nico who believes that the SA1100 is the same as the PXA255 in this respect. You also asked me to involve the watchdog maintainer which I tried to do but didn't hear anything back. There are only a couple of other drivers which can't stop the watchdog and there seems to be no consistancy regarding printing an error etc. I decided to print something since that matches the case for all the other drivers when NOWAYOUT is turned on. Also, I changed the device .name to "watchdog" like most of the other watchdogs. udev uses it as the device name (by default) and spaces etc. get in the way. Superceded 2833/1 because 2.6.13-rc4 caused rejects. Signed-off-by: Ian Campbell Signed-off-by: Russell King --- drivers/char/watchdog/sa1100_wdt.c | 49 ++++++++------------------------------ 1 file changed, 10 insertions(+), 39 deletions(-) diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index 1b2132617dc3..fb88b4041dca 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c @@ -36,13 +36,10 @@ #include #define OSCR_FREQ CLOCK_TICK_RATE -#define SA1100_CLOSE_MAGIC (0x5afc4453) static unsigned long sa1100wdt_users; -static int expect_close; static int pre_margin; static int boot_status; -static int nowayout = WATCHDOG_NOWAYOUT; /* * Allow only one person to hold it open @@ -62,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file) } /* - * Shut off the timer. - * Lock it in if it's a module and we defined ...NOWAYOUT - * Oddly, the watchdog can only be enabled, but we can turn off - * the interrupt, which appears to prevent the watchdog timing out. + * The watchdog cannot be disabled. + * + * Previous comments suggested that turning off the interrupt by + * clearing OIER[E3] would prevent the watchdog timing out but this + * does not appear to be true (at least on the PXA255). */ static int sa1100dog_release(struct inode *inode, struct file *file) { - OSMR3 = OSCR + pre_margin; - - if (expect_close == SA1100_CLOSE_MAGIC) { - OIER &= ~OIER_E3; - } else { - printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n"); - } + printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); clear_bit(1, &sa1100wdt_users); - expect_close = 0; return 0; } static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { - if (len) { - if (!nowayout) { - size_t i; - - expect_close = 0; - - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - expect_close = SA1100_CLOSE_MAGIC; - } - } + if (len) /* Refresh OSMR3 timer. */ OSMR3 = OSCR + pre_margin; - } return len; } static struct watchdog_info ident = { - .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | - WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, - .identity = "SA1100 Watchdog", + .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = "SA1100/PXA255 Watchdog", }; static int sa1100dog_ioctl(struct inode *inode, struct file *file, @@ -172,7 +147,7 @@ static struct file_operations sa1100dog_fops = static struct miscdevice sa1100dog_miscdev = { .minor = WATCHDOG_MINOR, - .name = "SA1100/PXA2xx watchdog", + .name = "watchdog", .fops = &sa1100dog_fops, }; @@ -194,7 +169,6 @@ static int __init sa1100dog_init(void) if (ret == 0) printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", margin); - return ret; } @@ -212,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog"); module_param(margin, int, 0); MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); - MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From 7b15f5e7bb180ac7bfb8926dbbd8835fecc07fad Mon Sep 17 00:00:00 2001 From: Luming Yu Date: Wed, 3 Aug 2005 17:38:04 -0400 Subject: [ACPI] revert Embedded Controller to polling-mode by default (ala 2.6.12) Burst mode isn't ready for prime time, but can be enabled for test via "ec_burst=1" Signed-off-by: Luming Yu Signed-off-by: Len Brown --- drivers/acpi/ec.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 2dadb7f63269..1ac5731d45e5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -76,13 +76,14 @@ static int acpi_ec_remove (struct acpi_device *device, int type); static int acpi_ec_start (struct acpi_device *device); static int acpi_ec_stop (struct acpi_device *device, int type); static int acpi_ec_burst_add ( struct acpi_device *device); +static int acpi_ec_polling_add ( struct acpi_device *device); static struct acpi_driver acpi_ec_driver = { .name = ACPI_EC_DRIVER_NAME, .class = ACPI_EC_CLASS, .ids = ACPI_EC_HID, .ops = { - .add = acpi_ec_burst_add, + .add = acpi_ec_polling_add, .remove = acpi_ec_remove, .start = acpi_ec_start, .stop = acpi_ec_stop, @@ -164,7 +165,7 @@ static union acpi_ec *ec_ecdt; /* External interfaces use first EC only, so remember */ static struct acpi_device *first_ec; -static int acpi_ec_polling_mode; +static int acpi_ec_polling_mode = EC_POLLING; /* -------------------------------------------------------------------------- Transaction Management @@ -1710,11 +1711,24 @@ static int __init acpi_fake_ecdt_setup(char *str) acpi_fake_ecdt_enabled = 1; return 0; } + __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); static int __init acpi_ec_set_polling_mode(char *str) { - acpi_ec_polling_mode = EC_POLLING; - acpi_ec_driver.ops.add = acpi_ec_polling_add; + int burst; + + if (!get_option(&str, &burst)) + return 0; + + if (burst) { + acpi_ec_polling_mode = EC_BURST; + acpi_ec_driver.ops.add = acpi_ec_burst_add; + } else { + acpi_ec_polling_mode = EC_POLLING; + acpi_ec_driver.ops.add = acpi_ec_polling_add; + } + printk(KERN_INFO PREFIX "EC %s mode.\n", + burst ? "burst": "polling"); return 0; } -__setup("ec_polling", acpi_ec_set_polling_mode); +__setup("ec_burst=", acpi_ec_set_polling_mode); -- cgit v1.2.3 From b34a8030eeab4d59dcdd86de38f6927b9edd441f Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 3 Aug 2005 17:55:21 -0400 Subject: [ACPI] restore /proc/acpi/button/ (ala 2.6.12) Signed-off-by Alexey Starikovskiy Signed-off-by Len Brown --- drivers/acpi/button.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 205 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 0f45d45f05a0..8162fd0c21a7 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include #include @@ -33,6 +36,9 @@ #define ACPI_BUTTON_COMPONENT 0x00080000 #define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver" #define ACPI_BUTTON_CLASS "button" +#define ACPI_BUTTON_FILE_INFO "info" +#define ACPI_BUTTON_FILE_STATE "state" +#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 #define ACPI_BUTTON_NOTIFY_STATUS 0x80 #define ACPI_BUTTON_SUBCLASS_POWER "power" @@ -64,6 +70,8 @@ MODULE_LICENSE("GPL"); static int acpi_button_add (struct acpi_device *device); static int acpi_button_remove (struct acpi_device *device, int type); +static int acpi_button_info_open_fs(struct inode *inode, struct file *file); +static int acpi_button_state_open_fs(struct inode *inode, struct file *file); static struct acpi_driver acpi_button_driver = { .name = ACPI_BUTTON_DRIVER_NAME, @@ -82,6 +90,179 @@ struct acpi_button { unsigned long pushed; }; +static struct file_operations acpi_button_info_fops = { + .open = acpi_button_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct file_operations acpi_button_state_fops = { + .open = acpi_button_state_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +/* -------------------------------------------------------------------------- + FS Interface (/proc) + -------------------------------------------------------------------------- */ + +static struct proc_dir_entry *acpi_button_dir; + +static int acpi_button_info_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_button *button = (struct acpi_button *) seq->private; + + ACPI_FUNCTION_TRACE("acpi_button_info_seq_show"); + + if (!button || !button->device) + return_VALUE(0); + + seq_printf(seq, "type: %s\n", + acpi_device_name(button->device)); + + return_VALUE(0); +} + +static int acpi_button_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_button_info_seq_show, PDE(inode)->data); +} + +static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_button *button = (struct acpi_button *) seq->private; + acpi_status status; + unsigned long state; + + ACPI_FUNCTION_TRACE("acpi_button_state_seq_show"); + + if (!button || !button->device) + return_VALUE(0); + + status = acpi_evaluate_integer(button->handle,"_LID",NULL,&state); + if (ACPI_FAILURE(status)) { + seq_printf(seq, "state: unsupported\n"); + } + else{ + seq_printf(seq, "state: %s\n", (state ? "open" : "closed")); + } + + return_VALUE(0); +} + +static int acpi_button_state_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_button_state_seq_show, PDE(inode)->data); +} + +static struct proc_dir_entry *acpi_power_dir; +static struct proc_dir_entry *acpi_sleep_dir; +static struct proc_dir_entry *acpi_lid_dir; + +static int +acpi_button_add_fs ( + struct acpi_device *device) +{ + struct proc_dir_entry *entry = NULL; + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_add_fs"); + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + button = acpi_driver_data(device); + + switch (button->type) { + case ACPI_BUTTON_TYPE_POWER: + case ACPI_BUTTON_TYPE_POWERF: + if (!acpi_power_dir) + acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, + acpi_button_dir); + entry = acpi_power_dir; + break; + case ACPI_BUTTON_TYPE_SLEEP: + case ACPI_BUTTON_TYPE_SLEEPF: + if (!acpi_sleep_dir) + acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, + acpi_button_dir); + entry = acpi_sleep_dir; + break; + case ACPI_BUTTON_TYPE_LID: + if (!acpi_lid_dir) + acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, + acpi_button_dir); + entry = acpi_lid_dir; + break; + } + + if (!entry) + return_VALUE(-ENODEV); + entry->owner = THIS_MODULE; + + acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); + if (!acpi_device_dir(device)) + return_VALUE(-ENODEV); + acpi_device_dir(device)->owner = THIS_MODULE; + + /* 'info' [R] */ + entry = create_proc_entry(ACPI_BUTTON_FILE_INFO, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BUTTON_FILE_INFO)); + else { + entry->proc_fops = &acpi_button_info_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + } + + /* show lid state [R] */ + if (button->type == ACPI_BUTTON_TYPE_LID) { + entry = create_proc_entry(ACPI_BUTTON_FILE_STATE, + S_IRUGO, acpi_device_dir(device)); + if (!entry) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Unable to create '%s' fs entry\n", + ACPI_BUTTON_FILE_INFO)); + else { + entry->proc_fops = &acpi_button_state_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + } + } + + return_VALUE(0); +} + + +static int +acpi_button_remove_fs ( + struct acpi_device *device) +{ + struct acpi_button *button = NULL; + + ACPI_FUNCTION_TRACE("acpi_button_remove_fs"); + + button = acpi_driver_data(device); + if (acpi_device_dir(device)) { + if (button->type == ACPI_BUTTON_TYPE_LID) + remove_proc_entry(ACPI_BUTTON_FILE_STATE, + acpi_device_dir(device)); + remove_proc_entry(ACPI_BUTTON_FILE_INFO, + acpi_device_dir(device)); + + remove_proc_entry(acpi_device_bid(device), + acpi_device_dir(device)->parent); + acpi_device_dir(device) = NULL; + } + + return_VALUE(0); +} + + /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -121,7 +302,8 @@ acpi_button_notify_fixed ( ACPI_FUNCTION_TRACE("acpi_button_notify_fixed"); - BUG_ON(!button); + if (!button) + return_ACPI_STATUS(AE_BAD_PARAMETER); acpi_button_notify(button->handle, ACPI_BUTTON_NOTIFY_STATUS, button); @@ -197,6 +379,10 @@ acpi_button_add ( goto end; } + result = acpi_button_add_fs(device); + if (result) + goto end; + switch (button->type) { case ACPI_BUTTON_TYPE_POWERF: status = acpi_install_fixed_event_handler ( @@ -240,6 +426,7 @@ acpi_button_add ( end: if (result) { + acpi_button_remove_fs(device); kfree(button); } @@ -280,6 +467,8 @@ acpi_button_remove (struct acpi_device *device, int type) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n")); + acpi_button_remove_fs(device); + kfree(button); return_VALUE(0); @@ -293,14 +482,20 @@ acpi_button_init (void) ACPI_FUNCTION_TRACE("acpi_button_init"); + acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); + if (!acpi_button_dir) + return_VALUE(-ENODEV); + acpi_button_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&acpi_button_driver); if (result < 0) { + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); return_VALUE(-ENODEV); } return_VALUE(0); } + static void __exit acpi_button_exit (void) { @@ -308,8 +503,17 @@ acpi_button_exit (void) acpi_bus_unregister_driver(&acpi_button_driver); + if (acpi_power_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir); + if (acpi_sleep_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir); + if (acpi_lid_dir) + remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); + return_VOID; } + module_init(acpi_button_init); module_exit(acpi_button_exit); -- cgit v1.2.3 From 79cda7d0e1c8629996242c036d6fe0466038d8ba Mon Sep 17 00:00:00 2001 From: Luming Yu Date: Wed, 3 Aug 2005 18:07:59 -0400 Subject: [ACPI] CONFIG_ACPI_HOTKEY is now "n" by default For 2.6.12 behaviour, this (EXPERIMENTAL) driver should not be built. Update the driver source with latest from Luming. Signed-off-by: Luming Yu Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 5 +- drivers/acpi/hotkey.c | 690 ++++++++++++++++++++++++++++---------------------- 2 files changed, 396 insertions(+), 299 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 84bbcb051cb7..281a64040f38 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -133,9 +133,10 @@ config ACPI_HOTKEY depends on ACPI_INTERPRETER depends on EXPERIMENTAL depends on !IA64_SGI_SN - default m + default n help - ACPI generic hotkey + Experimental consolidated hotkey driver. + If you are unsure, say N. config ACPI_FAN tristate "Fan" diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c index babdf762eadb..1f76a40badec 100644 --- a/drivers/acpi/hotkey.c +++ b/drivers/acpi/hotkey.c @@ -1,5 +1,5 @@ -/* - * hotkey.c - ACPI Hotkey Driver ($Revision:$) +/* + * hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $) * * Copyright (C) 2004 Luming Yu * @@ -51,17 +51,18 @@ #define ACPI_HOTKEY_POLLING 0x2 #define ACPI_UNDEFINED_EVENT 0xf -#define MAX_CONFIG_RECORD_LEN 80 -#define MAX_NAME_PATH_LEN 80 -#define MAX_CALL_PARM 80 +#define RESULT_STR_LEN 80 -#define IS_EVENT(e) 0xff /* ((e) & 0x40000000) */ -#define IS_POLL(e) 0xff /* (~((e) & 0x40000000)) */ +#define ACTION_METHOD 0 +#define POLL_METHOD 1 +#define IS_EVENT(e) ((e) <= 10000 && (e) >0) +#define IS_POLL(e) ((e) > 10000) +#define IS_OTHERS(e) ((e)<=0 || (e)>=20000) #define _COMPONENT ACPI_HOTKEY_COMPONENT ACPI_MODULE_NAME("acpi_hotkey") - MODULE_AUTHOR("luming.yu@intel.com"); +MODULE_AUTHOR("luming.yu@intel.com"); MODULE_DESCRIPTION(ACPI_HOTK_NAME); MODULE_LICENSE("GPL"); @@ -114,7 +115,7 @@ struct acpi_event_hotkey { char *action_method; /* action method */ }; -/* +/* * There are two ways to poll status * 1. directy call read_xxx method, without any arguments passed in * 2. call write_xxx method, with arguments passed in, you need @@ -131,7 +132,7 @@ struct acpi_polling_hotkey { char *poll_method; /* poll method */ acpi_handle action_handle; /* acpi handle attached action method */ char *action_method; /* action method */ - void *poll_result; /* polling_result */ + union acpi_object *poll_result; /* polling_result */ struct proc_dir_entry *proc; }; @@ -162,20 +163,25 @@ static struct acpi_driver hotkey_driver = { }, }; +static void free_hotkey_device(union acpi_hotkey *key); +static void free_hotkey_buffer(union acpi_hotkey *key); +static void free_poll_hotkey_buffer(union acpi_hotkey *key); static int hotkey_open_config(struct inode *inode, struct file *file); +static int hotkey_poll_open_config(struct inode *inode, struct file *file); static ssize_t hotkey_write_config(struct file *file, const char __user * buffer, size_t count, loff_t * data); -static ssize_t hotkey_write_poll_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data); static int hotkey_info_open_fs(struct inode *inode, struct file *file); static int hotkey_action_open_fs(struct inode *inode, struct file *file); static ssize_t hotkey_execute_aml_method(struct file *file, const char __user * buffer, size_t count, loff_t * data); static int hotkey_config_seq_show(struct seq_file *seq, void *offset); +static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset); static int hotkey_polling_open_fs(struct inode *inode, struct file *file); +static union acpi_hotkey *get_hotkey_by_event(struct + acpi_hotkey_list + *hotkey_list, int event); /* event based config */ static struct file_operations hotkey_config_fops = { @@ -188,9 +194,9 @@ static struct file_operations hotkey_config_fops = { /* polling based config */ static struct file_operations hotkey_poll_config_fops = { - .open = hotkey_open_config, + .open = hotkey_poll_open_config, .read = seq_read, - .write = hotkey_write_poll_config, + .write = hotkey_write_config, .llseek = seq_lseek, .release = single_release, }; @@ -227,7 +233,7 @@ static int hotkey_info_seq_show(struct seq_file *seq, void *offset) { ACPI_FUNCTION_TRACE("hotkey_info_seq_show"); - seq_printf(seq, "Hotkey generic driver ver: %s", HOTKEY_ACPI_VERSION); + seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION); return_VALUE(0); } @@ -239,27 +245,35 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file) static char *format_result(union acpi_object *object) { - char *buf = (char *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); - - memset(buf, 0, sizeof(union acpi_object)); + char *buf = NULL; + + buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL); + if (buf) + memset(buf, 0, RESULT_STR_LEN); + else + goto do_fail; /* Now, just support integer type */ if (object->type == ACPI_TYPE_INTEGER) - sprintf(buf, "%d", (u32) object->integer.value); - - return buf; + sprintf(buf, "%d\n", (u32) object->integer.value); +do_fail: + return (buf); } static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) { struct acpi_polling_hotkey *poll_hotkey = (struct acpi_polling_hotkey *)seq->private; + char *buf; ACPI_FUNCTION_TRACE("hotkey_polling_seq_show"); - if (poll_hotkey->poll_result) - seq_printf(seq, "%s", format_result(poll_hotkey->poll_result)); - + if (poll_hotkey->poll_result){ + buf = format_result(poll_hotkey->poll_result); + if(buf) + seq_printf(seq, "%s", buf); + kfree(buf); + } return_VALUE(0); } @@ -276,19 +290,19 @@ static int hotkey_action_open_fs(struct inode *inode, struct file *file) /* Mapping external hotkey number to standardized hotkey event num */ static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list) { - struct list_head *entries, *next; - int val = 0; + struct list_head *entries; + int val = -1; ACPI_FUNCTION_TRACE("hotkey_get_internal_event"); - list_for_each_safe(entries, next, list->entries) { + list_for_each(entries, list->entries) { union acpi_hotkey *key = container_of(entries, union acpi_hotkey, entries); if (key->link.hotkey_type == ACPI_HOTKEY_EVENT - && key->event_hotkey.external_hotkey_num == event) + && key->event_hotkey.external_hotkey_num == event){ val = key->link.hotkey_standard_num; - else - val = -1; + break; + } } return_VALUE(val); @@ -306,7 +320,7 @@ acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data) return_VOID; internal_event = hotkey_get_internal_event(event, &global_hotkey_list); - acpi_bus_generate_event(device, event, 0); + acpi_bus_generate_event(device, internal_event, 0); return_VOID; } @@ -329,13 +343,17 @@ static int auto_hotkey_remove(struct acpi_device *device, int type) static int create_polling_proc(union acpi_hotkey *device) { struct proc_dir_entry *proc; + char proc_name[80]; mode_t mode; ACPI_FUNCTION_TRACE("create_polling_proc"); mode = S_IFREG | S_IRUGO | S_IWUGO; - proc = create_proc_entry(device->poll_hotkey.action_method, - mode, hotkey_proc_dir); + sprintf(proc_name, "%d", device->link.hotkey_standard_num); + /* + strcat(proc_name, device->poll_hotkey.poll_method); + */ + proc = create_proc_entry(proc_name, mode, hotkey_proc_dir); if (!proc) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, @@ -353,23 +371,6 @@ static int create_polling_proc(union acpi_hotkey *device) return_VALUE(0); } -static int is_valid_acpi_path(const char *pathname) -{ - acpi_handle handle; - acpi_status status; - ACPI_FUNCTION_TRACE("is_valid_acpi_path"); - - status = acpi_get_handle(NULL, (char *)pathname, &handle); - return_VALUE(!ACPI_FAILURE(status)); -} - -static int is_valid_hotkey(union acpi_hotkey *device) -{ - ACPI_FUNCTION_TRACE("is_valid_hotkey"); - /* Implement valid check */ - return_VALUE(1); -} - static int hotkey_add(union acpi_hotkey *device) { int status = 0; @@ -378,15 +379,11 @@ static int hotkey_add(union acpi_hotkey *device) ACPI_FUNCTION_TRACE("hotkey_add"); if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) { - status = - acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); - if (status) - return_VALUE(status); - + acpi_bus_get_device(device->event_hotkey.bus_handle, &dev); status = acpi_install_notify_handler(dev->handle, - ACPI_SYSTEM_NOTIFY, + ACPI_DEVICE_NOTIFY, acpi_hotkey_notify_handler, - device); + dev); } else /* Add polling hotkey */ create_polling_proc(device); @@ -409,84 +406,143 @@ static int hotkey_remove(union acpi_hotkey *device) if (key->link.hotkey_standard_num == device->link.hotkey_standard_num) { list_del(&key->link.entries); - remove_proc_entry(key->poll_hotkey.action_method, - hotkey_proc_dir); + free_hotkey_device(key); global_hotkey_list.count--; break; } } + kfree(device); return_VALUE(0); } -static void hotkey_update(union acpi_hotkey *key) +static int hotkey_update(union acpi_hotkey *key) { - struct list_head *entries, *next; + struct list_head *entries; ACPI_FUNCTION_TRACE("hotkey_update"); - list_for_each_safe(entries, next, global_hotkey_list.entries) { - union acpi_hotkey *key = + list_for_each(entries, global_hotkey_list.entries) { + union acpi_hotkey *tmp= container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_standard_num == + if (tmp->link.hotkey_standard_num == key->link.hotkey_standard_num) { - key->event_hotkey.bus_handle = - key->event_hotkey.bus_handle; - key->event_hotkey.external_hotkey_num = - key->event_hotkey.external_hotkey_num; - key->event_hotkey.action_handle = - key->event_hotkey.action_handle; - key->event_hotkey.action_method = - key->event_hotkey.action_method; + if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { + free_hotkey_buffer(tmp); + tmp->event_hotkey.bus_handle = + key->event_hotkey.bus_handle; + tmp->event_hotkey.external_hotkey_num = + key->event_hotkey.external_hotkey_num; + tmp->event_hotkey.action_handle = + key->event_hotkey.action_handle; + tmp->event_hotkey.action_method = + key->event_hotkey.action_method; + kfree(key); + } else { + /* + char proc_name[80]; + + sprintf(proc_name, "%d", tmp->link.hotkey_standard_num); + strcat(proc_name, tmp->poll_hotkey.poll_method); + remove_proc_entry(proc_name,hotkey_proc_dir); + */ + free_poll_hotkey_buffer(tmp); + tmp->poll_hotkey.poll_handle = + key->poll_hotkey.poll_handle; + tmp->poll_hotkey.poll_method = + key->poll_hotkey.poll_method; + tmp->poll_hotkey.action_handle = + key->poll_hotkey.action_handle; + tmp->poll_hotkey.action_method = + key->poll_hotkey.action_method; + tmp->poll_hotkey.poll_result = + key->poll_hotkey.poll_result; + /* + create_polling_proc(tmp); + */ + kfree(key); + } + return_VALUE(0); break; } } - return_VOID; + return_VALUE(-ENODEV); } static void free_hotkey_device(union acpi_hotkey *key) { struct acpi_device *dev; - int status; ACPI_FUNCTION_TRACE("free_hotkey_device"); if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { - status = - acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); + acpi_bus_get_device(key->event_hotkey.bus_handle, &dev); if (dev->handle) acpi_remove_notify_handler(dev->handle, - ACPI_SYSTEM_NOTIFY, + ACPI_DEVICE_NOTIFY, acpi_hotkey_notify_handler); - } else - remove_proc_entry(key->poll_hotkey.action_method, - hotkey_proc_dir); + free_hotkey_buffer(key); + } else { + char proc_name[80]; + + sprintf(proc_name, "%d", key->link.hotkey_standard_num); + /* + strcat(proc_name, key->poll_hotkey.poll_method); + */ + remove_proc_entry(proc_name,hotkey_proc_dir); + free_poll_hotkey_buffer(key); + } kfree(key); return_VOID; } +static void +free_hotkey_buffer(union acpi_hotkey *key) +{ + kfree(key->event_hotkey.action_method); +} + +static void +free_poll_hotkey_buffer(union acpi_hotkey *key) +{ + kfree(key->poll_hotkey.action_method); + kfree(key->poll_hotkey.poll_method); + kfree(key->poll_hotkey.poll_result); +} static int init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str, char *method, int std_num, int external_num) { + acpi_handle tmp_handle; + acpi_status status = AE_OK; + ACPI_FUNCTION_TRACE("init_hotkey_device"); + if(std_num < 0 || IS_POLL(std_num) || !key ) + goto do_fail; + + if(!bus_str || !action_str || !method) + goto do_fail; + key->link.hotkey_type = ACPI_HOTKEY_EVENT; key->link.hotkey_standard_num = std_num; key->event_hotkey.flag = 0; - if (is_valid_acpi_path(bus_str)) - acpi_get_handle((acpi_handle) 0, - bus_str, &(key->event_hotkey.bus_handle)); - else - return_VALUE(-ENODEV); - key->event_hotkey.external_hotkey_num = external_num; - if (is_valid_acpi_path(action_str)) - acpi_get_handle((acpi_handle) 0, - action_str, &(key->event_hotkey.action_handle)); - key->event_hotkey.action_method = kmalloc(sizeof(method), GFP_KERNEL); - strcpy(key->event_hotkey.action_method, method); + key->event_hotkey.action_method = method; - return_VALUE(!is_valid_hotkey(key)); + status = acpi_get_handle(NULL,bus_str, &(key->event_hotkey.bus_handle)); + if(ACPI_FAILURE(status)) + goto do_fail; + key->event_hotkey.external_hotkey_num = external_num; + status = acpi_get_handle(NULL,action_str, &(key->event_hotkey.action_handle)); + if(ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(key->event_hotkey.action_handle, + method, &tmp_handle); + if (ACPI_FAILURE(status)) + goto do_fail; + return_VALUE(AE_OK); +do_fail: + return_VALUE(-ENODEV); } static int @@ -495,34 +551,46 @@ init_poll_hotkey_device(union acpi_hotkey *key, char *poll_method, char *action_str, char *action_method, int std_num) { + acpi_status status = AE_OK; + acpi_handle tmp_handle; + ACPI_FUNCTION_TRACE("init_poll_hotkey_device"); + if(std_num < 0 || IS_EVENT(std_num) || !key) + goto do_fail; + + if(!poll_str || !poll_method || !action_str || !action_method) + goto do_fail; + key->link.hotkey_type = ACPI_HOTKEY_POLLING; key->link.hotkey_standard_num = std_num; key->poll_hotkey.flag = 0; - if (is_valid_acpi_path(poll_str)) - acpi_get_handle((acpi_handle) 0, - poll_str, &(key->poll_hotkey.poll_handle)); - else - return_VALUE(-ENODEV); key->poll_hotkey.poll_method = poll_method; - if (is_valid_acpi_path(action_str)) - acpi_get_handle((acpi_handle) 0, - action_str, &(key->poll_hotkey.action_handle)); - key->poll_hotkey.action_method = - kmalloc(sizeof(action_method), GFP_KERNEL); - strcpy(key->poll_hotkey.action_method, action_method); + key->poll_hotkey.action_method = action_method; + + status = acpi_get_handle(NULL,poll_str, &(key->poll_hotkey.poll_handle)); + if(ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(key->poll_hotkey.poll_handle, + poll_method, &tmp_handle); + if (ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(NULL,action_str, &(key->poll_hotkey.action_handle)); + if (ACPI_FAILURE(status)) + goto do_fail; + status = acpi_get_handle(key->poll_hotkey.action_handle, + action_method, &tmp_handle); + if (ACPI_FAILURE(status)) + goto do_fail; key->poll_hotkey.poll_result = (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); - return_VALUE(is_valid_hotkey(key)); + if(!key->poll_hotkey.poll_result) + goto do_fail; + return_VALUE(AE_OK); +do_fail: + return_VALUE(-ENODEV); } -static int check_hotkey_valid(union acpi_hotkey *key, - struct acpi_hotkey_list *list) -{ - ACPI_FUNCTION_TRACE("check_hotkey_valid"); - return_VALUE(0); -} static int hotkey_open_config(struct inode *inode, struct file *file) { @@ -531,10 +599,17 @@ static int hotkey_open_config(struct inode *inode, struct file *file) (file, hotkey_config_seq_show, PDE(inode)->data)); } +static int hotkey_poll_open_config(struct inode *inode, struct file *file) +{ + ACPI_FUNCTION_TRACE("hotkey_poll_open_config"); + return_VALUE(single_open + (file, hotkey_poll_config_seq_show, PDE(inode)->data)); +} + static int hotkey_config_seq_show(struct seq_file *seq, void *offset) { struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - struct list_head *entries, *next; + struct list_head *entries; char bus_name[ACPI_PATHNAME_MAX] = { 0 }; char action_name[ACPI_PATHNAME_MAX] = { 0 }; struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; @@ -542,10 +617,7 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); - if (!hotkey_list) - goto end; - - list_for_each_safe(entries, next, hotkey_list->entries) { + list_for_each(entries, hotkey_list->entries) { union acpi_hotkey *key = container_of(entries, union acpi_hotkey, entries); if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) { @@ -553,18 +625,37 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) ACPI_NAME_TYPE_MAX, &bus); acpi_get_name(key->event_hotkey.action_handle, ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%d:%d", bus_name, + seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name, action_name, key->event_hotkey.action_method, key->link.hotkey_standard_num, key->event_hotkey.external_hotkey_num); - } /* ACPI_HOTKEY_POLLING */ - else { + } + } + seq_puts(seq, "\n"); + return_VALUE(0); +} + +static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset) +{ + struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; + struct list_head *entries; + char bus_name[ACPI_PATHNAME_MAX] = { 0 }; + char action_name[ACPI_PATHNAME_MAX] = { 0 }; + struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name }; + struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name }; + + ACPI_FUNCTION_TRACE(("hotkey_config_seq_show")); + + list_for_each(entries, hotkey_list->entries) { + union acpi_hotkey *key = + container_of(entries, union acpi_hotkey, entries); + if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) { acpi_get_name(key->poll_hotkey.poll_handle, ACPI_NAME_TYPE_MAX, &bus); acpi_get_name(key->poll_hotkey.action_handle, ACPI_NAME_TYPE_MAX, &act); - seq_printf(seq, "%s:%s:%s:%s:%d", bus_name, + seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name, key->poll_hotkey.poll_method, action_name, key->poll_hotkey.action_method, @@ -572,49 +663,83 @@ static int hotkey_config_seq_show(struct seq_file *seq, void *offset) } } seq_puts(seq, "\n"); - end: return_VALUE(0); } static int get_parms(char *config_record, int *cmd, - char *bus_handle, - char *bus_method, - char *action_handle, - char *method, int *internal_event_num, int *external_event_num) + char **bus_handle, + char **bus_method, + char **action_handle, + char **method, int *internal_event_num, int *external_event_num) { - char *tmp, *tmp1; + char *tmp, *tmp1, count; ACPI_FUNCTION_TRACE(("get_parms")); sscanf(config_record, "%d", cmd); + if(*cmd == 1){ + if(sscanf(config_record, "%d:%d", cmd, internal_event_num)!=2) + goto do_fail; + else + return (6); + } tmp = strchr(config_record, ':'); + if (!tmp) + goto do_fail; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(bus_handle, tmp, tmp1 - tmp); - bus_handle[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + + count = tmp1 - tmp; + *bus_handle = (char *) kmalloc(count+1, GFP_KERNEL); + if(!*bus_handle) + goto do_fail; + strncpy(*bus_handle, tmp, count); + *(*bus_handle + count) = 0; tmp = tmp1; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(bus_method, tmp, tmp1 - tmp); - bus_method[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *bus_method = (char *) kmalloc(count+1, GFP_KERNEL); + if(!*bus_method) + goto do_fail; + strncpy(*bus_method, tmp, count); + *(*bus_method + count) = 0; tmp = tmp1; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(action_handle, tmp, tmp1 - tmp); - action_handle[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *action_handle = (char *) kmalloc(count+1, GFP_KERNEL); + strncpy(*action_handle, tmp, count); + *(*action_handle + count) = 0; tmp = tmp1; tmp++; tmp1 = strchr(tmp, ':'); - strncpy(method, tmp, tmp1 - tmp); - method[tmp1 - tmp] = 0; + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *method = (char *) kmalloc(count+1, GFP_KERNEL); + if(!*method) + goto do_fail; + strncpy(*method, tmp, count); + *(*method + count) = 0; + + if(sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num)<=0) + goto do_fail; - sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num); return_VALUE(6); +do_fail: + return_VALUE(-1); } /* count is length for one input record */ @@ -622,135 +747,117 @@ static ssize_t hotkey_write_config(struct file *file, const char __user * buffer, size_t count, loff_t * data) { - struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - char config_record[MAX_CONFIG_RECORD_LEN]; - char bus_handle[MAX_NAME_PATH_LEN]; - char bus_method[MAX_NAME_PATH_LEN]; - char action_handle[MAX_NAME_PATH_LEN]; - char method[20]; + char *config_record = NULL; + char *bus_handle = NULL; + char *bus_method = NULL; + char *action_handle = NULL; + char *method = NULL; int cmd, internal_event_num, external_event_num; int ret = 0; union acpi_hotkey *key = NULL; ACPI_FUNCTION_TRACE(("hotkey_write_config")); - if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); - return_VALUE(-EINVAL); - } + config_record = (char *) kmalloc(count+1, GFP_KERNEL); + if(!config_record) + return_VALUE(-ENOMEM); if (copy_from_user(config_record, buffer, count)) { + kfree(config_record); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); return_VALUE(-EINVAL); } - config_record[count] = '\0'; + config_record[count] = 0; ret = get_parms(config_record, &cmd, - bus_handle, - bus_method, - action_handle, - method, &internal_event_num, &external_event_num); + &bus_handle, + &bus_method, + &action_handle, + &method, &internal_event_num, &external_event_num); + + kfree(config_record); + if(IS_OTHERS(internal_event_num)) + goto do_fail; if (ret != 6) { +do_fail: + kfree(bus_handle); + kfree(bus_method); + kfree(action_handle); + kfree(method); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format ret=%d\n", ret)); return_VALUE(-EINVAL); } key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - ret = init_hotkey_device(key, bus_handle, action_handle, method, + if(!key) + goto do_fail; + memset(key, 0, sizeof(union acpi_hotkey)); + if(cmd == 1) { + union acpi_hotkey *tmp = NULL; + tmp = get_hotkey_by_event(&global_hotkey_list, + internal_event_num); + if(!tmp) + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid key")); + else + memcpy(key, tmp, sizeof(union acpi_hotkey)); + goto cont_cmd; + } + if (IS_EVENT(internal_event_num)) { + kfree(bus_method); + ret = init_hotkey_device(key, bus_handle, action_handle, method, internal_event_num, external_event_num); - - if (ret || check_hotkey_valid(key, hotkey_list)) { + } else + ret = init_poll_hotkey_device(key, bus_handle, bus_method, + action_handle, method, + internal_event_num); + if (ret) { + kfree(bus_handle); + kfree(action_handle); + if(IS_EVENT(internal_event_num)) + free_hotkey_buffer(key); + else + free_poll_hotkey_buffer(key); kfree(key); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); return_VALUE(-EINVAL); } - switch (cmd) { - case 0: - hotkey_add(key); - break; - case 1: - hotkey_remove(key); - free_hotkey_device(key); - break; - case 2: - hotkey_update(key); - break; - default: - break; - } - return_VALUE(count); -} - -/* count is length for one input record */ -static ssize_t hotkey_write_poll_config(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - struct seq_file *m = (struct seq_file *)file->private_data; - struct acpi_hotkey_list *hotkey_list = - (struct acpi_hotkey_list *)m->private; - - char config_record[MAX_CONFIG_RECORD_LEN]; - char polling_handle[MAX_NAME_PATH_LEN]; - char action_handle[MAX_NAME_PATH_LEN]; - char poll_method[20], action_method[20]; - int ret, internal_event_num, cmd, external_event_num; - union acpi_hotkey *key = NULL; - - ACPI_FUNCTION_TRACE("hotkey_write_poll_config"); - - if (!hotkey_list || count > MAX_CONFIG_RECORD_LEN) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid arguments\n")); - return_VALUE(-EINVAL); - } - - if (copy_from_user(config_record, buffer, count)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data \n")); - return_VALUE(-EINVAL); - } - config_record[count] = '\0'; - ret = get_parms(config_record, - &cmd, - polling_handle, - poll_method, - action_handle, - action_method, - &internal_event_num, &external_event_num); - - if (ret != 6) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); - return_VALUE(-EINVAL); - } +cont_cmd: + kfree(bus_handle); + kfree(action_handle); - key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); - ret = init_poll_hotkey_device(key, polling_handle, poll_method, - action_handle, action_method, - internal_event_num); - if (ret || check_hotkey_valid(key, hotkey_list)) { - kfree(key); - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid hotkey \n")); - return_VALUE(-EINVAL); - } switch (cmd) { case 0: - hotkey_add(key); + if(get_hotkey_by_event(&global_hotkey_list,key->link.hotkey_standard_num)) + goto fail_out; + else + hotkey_add(key); break; case 1: hotkey_remove(key); break; case 2: - hotkey_update(key); + if(hotkey_update(key)) + goto fail_out; break; default: + goto fail_out; break; } return_VALUE(count); +fail_out: + if(IS_EVENT(internal_event_num)) + free_hotkey_buffer(key); + else + free_poll_hotkey_buffer(key); + kfree(key); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "invalid key\n")); + return_VALUE(-EINVAL); } -/* +/* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output * of the method is written is output, which can also be NULL @@ -775,7 +882,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, return_VALUE(status == AE_OK); } -static int read_acpi_int(acpi_handle handle, const char *method, int *val) +static int read_acpi_int(acpi_handle handle, const char *method, union acpi_object *val) { struct acpi_buffer output; union acpi_object out_obj; @@ -786,62 +893,32 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val) output.pointer = &out_obj; status = acpi_evaluate_object(handle, (char *)method, NULL, &output); - *val = out_obj.integer.value; + if(val){ + val->integer.value = out_obj.integer.value; + val->type = out_obj.type; + } else + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "null val pointer")); return_VALUE((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)); } -static acpi_handle -get_handle_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, int event_num) +static union acpi_hotkey *get_hotkey_by_event(struct + acpi_hotkey_list + *hotkey_list, int event) { - struct list_head *entries, *next; - - list_for_each_safe(entries, next, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT - && key->link.hotkey_standard_num == event_num) { - return (key->event_hotkey.action_handle); - } - } - return (NULL); -} - -static -char *get_method_from_hotkeylist(struct acpi_hotkey_list *hotkey_list, - int event_num) -{ - struct list_head *entries, *next; - - list_for_each_safe(entries, next, hotkey_list->entries) { - union acpi_hotkey *key = - container_of(entries, union acpi_hotkey, entries); - - if (key->link.hotkey_type == ACPI_HOTKEY_EVENT && - key->link.hotkey_standard_num == event_num) - return (key->event_hotkey.action_method); - } - return (NULL); -} - -static struct acpi_polling_hotkey *get_hotkey_by_event(struct - acpi_hotkey_list - *hotkey_list, int event) -{ - struct list_head *entries, *next; + struct list_head *entries; - list_for_each_safe(entries, next, hotkey_list->entries) { + list_for_each(entries, hotkey_list->entries) { union acpi_hotkey *key = container_of(entries, union acpi_hotkey, entries); - if (key->link.hotkey_type == ACPI_HOTKEY_POLLING - && key->link.hotkey_standard_num == event) { - return (&key->poll_hotkey); + if (key->link.hotkey_standard_num == event) { + return(key); } } - return (NULL); + return(NULL); } -/* +/* * user call AML method interface: * Call convention: * echo "event_num: arg type : value" @@ -854,48 +931,56 @@ static ssize_t hotkey_execute_aml_method(struct file *file, size_t count, loff_t * data) { struct acpi_hotkey_list *hotkey_list = &global_hotkey_list; - char arg[MAX_CALL_PARM]; - int event, type, value; - - char *method; - acpi_handle handle; + char *arg; + int event,method_type,type, value; + union acpi_hotkey *key; ACPI_FUNCTION_TRACE("hotkey_execte_aml_method"); - if (!hotkey_list || count > MAX_CALL_PARM) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 1")); - return_VALUE(-EINVAL); - } + arg = (char *) kmalloc(count+1, GFP_KERNEL); + if(!arg) + return_VALUE(-ENOMEM); + arg[count]=0; if (copy_from_user(arg, buffer, count)) { + kfree(arg); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 2")); return_VALUE(-EINVAL); } - arg[count] = '\0'; - - if (sscanf(arg, "%d:%d:%d", &event, &type, &value) != 3) { + if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) != 4) { + kfree(arg); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument 3")); return_VALUE(-EINVAL); } - + kfree(arg); if (type == ACPI_TYPE_INTEGER) { - handle = get_handle_from_hotkeylist(hotkey_list, event); - method = (char *)get_method_from_hotkeylist(hotkey_list, event); + key = get_hotkey_by_event(hotkey_list, event); + if(!key) + goto do_fail; if (IS_EVENT(event)) - write_acpi_int(handle, method, value, NULL); + write_acpi_int(key->event_hotkey.action_handle, + key->event_hotkey.action_method, value, NULL); else if (IS_POLL(event)) { - struct acpi_polling_hotkey *key; - key = (struct acpi_polling_hotkey *) - get_hotkey_by_event(hotkey_list, event); - read_acpi_int(handle, method, key->poll_result); + if ( method_type == POLL_METHOD ) + read_acpi_int(key->poll_hotkey.poll_handle, + key->poll_hotkey.poll_method, + key->poll_hotkey.poll_result); + else if ( method_type == ACTION_METHOD ) + write_acpi_int(key->poll_hotkey.action_handle, + key->poll_hotkey.action_method, value, NULL); + else + goto do_fail; + } } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Not supported")); return_VALUE(-EINVAL); } - return_VALUE(count); +do_fail: + return_VALUE(-EINVAL); + } static int __init hotkey_init(void) @@ -928,7 +1013,7 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_EV_CONFIG)); - return (-ENODEV); + goto do_fail1; } else { hotkey_config->proc_fops = &hotkey_config_fops; hotkey_config->data = &global_hotkey_list; @@ -943,7 +1028,8 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_EV_CONFIG)); - return (-ENODEV); + + goto do_fail2; } else { hotkey_poll_config->proc_fops = &hotkey_poll_config_fops; hotkey_poll_config->data = &global_hotkey_list; @@ -957,7 +1043,7 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_ACTION)); - return (-ENODEV); + goto do_fail3; } else { hotkey_action->proc_fops = &hotkey_action_fops; hotkey_action->owner = THIS_MODULE; @@ -970,7 +1056,7 @@ static int __init hotkey_init(void) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hotkey: Unable to create %s entry\n", HOTKEY_INFO)); - return (-ENODEV); + goto do_fail4; } else { hotkey_info->proc_fops = &hotkey_info_fops; hotkey_info->owner = THIS_MODULE; @@ -979,23 +1065,33 @@ static int __init hotkey_init(void) } result = acpi_bus_register_driver(&hotkey_driver); - if (result < 0) { - remove_proc_entry(HOTKEY_PROC, acpi_root_dir); - return (-ENODEV); - } + if (result < 0) + goto do_fail5; global_hotkey_list.count = 0; global_hotkey_list.entries = &hotkey_entries; INIT_LIST_HEAD(&hotkey_entries); return (0); + +do_fail5: + remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir); +do_fail4: + remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir); +do_fail3: + remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir); +do_fail2: + remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir); +do_fail1: + remove_proc_entry(HOTKEY_PROC, acpi_root_dir); + return (-ENODEV); } static void __exit hotkey_exit(void) { struct list_head *entries, *next; - ACPI_FUNCTION_TRACE("hotkey_remove"); + ACPI_FUNCTION_TRACE("hotkey_exit"); list_for_each_safe(entries, next, global_hotkey_list.entries) { union acpi_hotkey *key = -- cgit v1.2.3 From d4ab025b73a2d10548e17765eb76f3b7351dc611 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 3 Aug 2005 23:20:58 -0400 Subject: [ACPI] delete Warning: Encountered executable code at module level, [AE_NOT_CONFIGURED] http://bugzilla.kernel.org/show_bug.cgi?id=4923 Signed-off-by: Len Brown --- drivers/acpi/dispatcher/dswload.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 1ac197ccfc80..d11620018421 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -491,12 +491,6 @@ acpi_ds_load2_begin_op ( if ((!(walk_state->op_info->flags & AML_NSOPCODE) && (walk_state->opcode != AML_INT_NAMEPATH_OP)) || (!(walk_state->op_info->flags & AML_NAMED))) { - if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || - (walk_state->op_info->class == AML_CLASS_CONTROL)) { - ACPI_REPORT_WARNING (( - "Encountered executable code at module level, [%s]\n", - acpi_ps_get_opcode_name (walk_state->opcode))); - } return_ACPI_STATUS (AE_OK); } -- cgit v1.2.3 From 11e981f1e02c2a36465cbb208b21cb8b6480f399 Mon Sep 17 00:00:00 2001 From: David Shaohua Li Date: Wed, 3 Aug 2005 23:46:33 -0400 Subject: [ACPI] S3 resume: avoid kmalloc() might_sleep oops symptom ACPI now uses kmalloc(...,GPF_ATOMIC) during suspend/resume. http://bugzilla.kernel.org/show_bug.cgi?id=3469 Signed-off-by: David Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/osl.c | 6 +++++- drivers/acpi/pci_link.c | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index bdd9f37f8101..7289da3c4db6 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -145,10 +145,14 @@ acpi_os_vprintf(const char *fmt, va_list args) #endif } +extern int acpi_in_resume; void * acpi_os_allocate(acpi_size size) { - return kmalloc(size, GFP_KERNEL); + if (acpi_in_resume) + return kmalloc(size, GFP_ATOMIC); + else + return kmalloc(size, GFP_KERNEL); } void diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 65cea07abbc3..834c2ceff1aa 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -798,6 +798,11 @@ acpi_pci_link_resume( return_VALUE(0); } +/* + * FIXME: this is a workaround to avoid nasty warning. It will be removed + * after every device calls pci_disable_device in .resume. + */ +int acpi_in_resume; static int irqrouter_resume( struct sys_device *dev) @@ -807,6 +812,7 @@ irqrouter_resume( ACPI_FUNCTION_TRACE("irqrouter_resume"); + acpi_in_resume = 1; list_for_each(node, &acpi_link.entries) { link = list_entry(node, struct acpi_pci_link, node); if (!link) { @@ -816,6 +822,7 @@ irqrouter_resume( } acpi_pci_link_resume(link); } + acpi_in_resume = 0; return_VALUE(0); } -- cgit v1.2.3 From ff2afb9df607dfcaacdaf67ea84b773c6fb08f4c Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 4 Aug 2005 14:17:33 +0100 Subject: [PATCH] ARM: Fix ARM fault handler for get_user_pages() fixes. The ARM fault handler is optimised to make the fast path, err, fast. The renumbering of the VM_FAULT_* codes broke this because numbers were used instead of the definitions. Fix this. Signed-off-by: Russell King --- arch/arm/mm/fault.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 65bfe84b6d67..0b6c4db44e08 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -238,9 +238,9 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) up_read(&mm->mmap_sem); /* - * Handle the "normal" case first + * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR */ - if (fault > 0) + if (fault >= VM_FAULT_MINOR) return 0; /* @@ -261,7 +261,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) do_exit(SIGKILL); return 0; - case 0: + case VM_FAULT_SIGBUS: /* * We had some memory, but were unable to * successfully fix up this page fault. -- cgit v1.2.3 From 3873658be7b3896e88648664e480a44d12083ad8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 4 Aug 2005 07:05:37 -0700 Subject: [SPARC]: Fix up sleep_on() removal in vfc driver. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/sbus/char/vfc.h | 2 -- drivers/sbus/char/vfc_dev.c | 1 - drivers/sbus/char/vfc_i2c.c | 19 ++----------------- 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h index e56a43af0f62..a7782e7da42e 100644 --- a/drivers/sbus/char/vfc.h +++ b/drivers/sbus/char/vfc.h @@ -129,8 +129,6 @@ struct vfc_dev { struct vfc_regs *phys_regs; unsigned int control_reg; struct semaphore device_lock_sem; - struct timer_list poll_timer; - wait_queue_head_t poll_wait; int instance; int busy; unsigned long which_io; diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 86ce54130954..7a103698fa3c 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -137,7 +137,6 @@ int init_vfc_devstruct(struct vfc_dev *dev, int instance) dev->instance=instance; init_MUTEX(&dev->device_lock_sem); dev->control_reg=0; - init_waitqueue_head(&dev->poll_wait); dev->busy=0; return 0; } diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c index 1faf1e75f71f..739cad9b19a1 100644 --- a/drivers/sbus/char/vfc_i2c.c +++ b/drivers/sbus/char/vfc_i2c.c @@ -79,25 +79,10 @@ int vfc_pcf8584_init(struct vfc_dev *dev) return 0; } -void vfc_i2c_delay_wakeup(struct vfc_dev *dev) -{ - /* Used to profile code and eliminate too many delays */ - VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n", dev->instance)); - wake_up(&dev->poll_wait); -} - void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) { - DEFINE_WAIT(wait); - init_timer(&dev->poll_timer); - dev->poll_timer.expires = jiffies + usecs_to_jiffies(usecs); - dev->poll_timer.data=(unsigned long)dev; - dev->poll_timer.function=(void *)(unsigned long)vfc_i2c_delay_wakeup; - add_timer(&dev->poll_timer); - prepare_to_wait(&dev->poll_wait, &wait, TASK_UNINTERRUPTIBLE); - schedule(); - del_timer(&dev->poll_timer); - finish_wait(&dev->poll_wait, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(usecs)); } void inline vfc_i2c_delay(struct vfc_dev *dev) -- cgit v1.2.3 From c013622d5fe0ffeb0c74b2af4c2b1aad6164f709 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Thu, 4 Aug 2005 15:06:59 +0100 Subject: [PATCH] ARM: 2838/1: Fix arm oprofile backtrace warning Patch from Richard Purdie Fix a typo causing a warning in the arm oprofile backtrace code. Signed-off-by: Richard Purdie Signed-off-by: Russell King --- arch/arm/oprofile/backtrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/oprofile/backtrace.c b/arch/arm/oprofile/backtrace.c index ec58d3e2eb8b..df35c452a8bf 100644 --- a/arch/arm/oprofile/backtrace.c +++ b/arch/arm/oprofile/backtrace.c @@ -115,7 +115,7 @@ static int valid_kernel_stack(struct frame_tail *tail, struct pt_regs *regs) return (tailaddr > stack) && (tailaddr < stack_base); } -void arm_backtrace(struct pt_regs const *regs, unsigned int depth) +void arm_backtrace(struct pt_regs * const regs, unsigned int depth) { struct frame_tail *tail; unsigned long last_address = 0; -- cgit v1.2.3 From c36f19e02a96488f550fdb678c92500afca3109b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 4 Aug 2005 11:36:26 +0200 Subject: [PATCH] Remove suspend() calls from shutdown path This removes the calls to device_suspend() from the shutdown path that were added sometime during 2.6.13-rc*. They aren't working properly on a number of configs (I got reports from both ppc powerbook users and x86 users) causing the system to not shutdown anymore. I think it isn't the right approach at the moment anyway. We have already a shutdown() callback for the drivers that actually care about shutdown and the suspend() code isn't yet in a good enough shape to be so much generalized. Also, the semantics of suspend and shutdown are slightly different on a number of setups and the way this was patched in provides little way for drivers to cleanly differenciate. It should have been at least a different message. For 2.6.13, I think we should revert to 2.6.12 behaviour and have a working suspend back. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds --- kernel/sys.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/sys.c b/kernel/sys.c index 000e81ad2c1d..0bcaed6560ac 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -404,7 +404,6 @@ void kernel_halt(void) { notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); system_state = SYSTEM_HALT; - device_suspend(PMSG_SUSPEND); device_shutdown(); printk(KERN_EMERG "System halted.\n"); machine_halt(); @@ -415,7 +414,6 @@ void kernel_power_off(void) { notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); system_state = SYSTEM_POWER_OFF; - device_suspend(PMSG_SUSPEND); device_shutdown(); printk(KERN_EMERG "Power down.\n"); machine_power_off(); -- cgit v1.2.3 From 1260f801b4e4ba7be200886b4a53d730de05ca19 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 4 Aug 2005 11:50:01 +0100 Subject: [PATCH] Keys: Fix key management syscall interface bugs This fixes five bugs in the key management syscall interface: (1) add_key() returns 0 rather than EINVAL if the key type is "". Checking the key type isn't "" should be left to lookup_user_key(). (2) request_key() returns ENOKEY rather than EPERM if the key type begins with a ".". lookup_user_key() can't do this because internal key types begin with a ".". (3) Key revocation always returns 0, even if it fails. (4) Key read can return EAGAIN rather than EACCES under some circumstances. A key is permitted to by read by a process if it doesn't grant read access, but it does grant search access and it is in the process's keyrings. That search returns EAGAIN if it fails, and this needs translating to EACCES. (5) request_key() never adds the new key to the destination keyring if one is supplied. The wrong macro was being used to test for an error condition: PTR_ERR() will always return true, whether or not there's an error; this should've been IS_ERR(). Signed-Off-By: David Howells Signed-Off-By: Linus Torvalds --- security/keys/keyctl.c | 11 +++++++---- security/keys/request_key.c | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index fea262860ea0..a6516a64b297 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -49,9 +49,6 @@ asmlinkage long sys_add_key(const char __user *_type, goto error; type[31] = '\0'; - if (!type[0]) - goto error; - ret = -EPERM; if (type[0] == '.') goto error; @@ -144,6 +141,10 @@ asmlinkage long sys_request_key(const char __user *_type, goto error; type[31] = '\0'; + ret = -EPERM; + if (type[0] == '.') + goto error; + /* pull the description into kernel space */ ret = -EFAULT; dlen = strnlen_user(_description, PAGE_SIZE - 1); @@ -362,7 +363,7 @@ long keyctl_revoke_key(key_serial_t id) key_put(key); error: - return 0; + return ret; } /* end keyctl_revoke_key() */ @@ -685,6 +686,8 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) goto can_read_key2; ret = PTR_ERR(skey); + if (ret == -EAGAIN) + ret = -EACCES; goto error2; } diff --git a/security/keys/request_key.c b/security/keys/request_key.c index dfcd983af1fd..90c1506d007c 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -405,7 +405,7 @@ struct key *request_key_and_link(struct key_type *type, key_user_put(user); /* link the new key into the appropriate keyring */ - if (!PTR_ERR(key)) + if (!IS_ERR(key)) request_key_link(key, dest_keyring); } -- cgit v1.2.3 From 968002166cce2ef4ead8c9441a9dd5b945c9ed1e Mon Sep 17 00:00:00 2001 From: Alexander Nyberg Date: Thu, 4 Aug 2005 16:14:57 +0200 Subject: [PATCH] x86-64: use proper VM_FAULT_xxx macros x86_64 had hardcoded the VM_ numbers so it broke down when the numbers were changed. Signed-off-by: Alexander Nyberg Signed-off-by: Linus Torvalds --- arch/x86_64/mm/fault.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 13792721037e..493819e543a5 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -439,13 +439,13 @@ good_area: * the fault. */ switch (handle_mm_fault(mm, vma, address, write)) { - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; default: goto out_of_memory; -- cgit v1.2.3 From 6e346228c76506e07e297744a28464022c6806ad Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 4 Aug 2005 08:33:38 -0700 Subject: It wasn't just x86-64 that had hardcoded VM_FAULT_xxx numbers Fix up arm26, cris, frv, m68k, parisc and sh64 too.. --- arch/arm26/mm/fault.c | 17 +++++++---------- arch/cris/mm/fault.c | 6 +++--- arch/frv/mm/fault.c | 6 +++--- arch/m68k/mm/fault.c | 6 +++--- arch/parisc/mm/fault.c | 12 ++++++------ arch/sh64/mm/fault.c | 6 +++--- 6 files changed, 25 insertions(+), 28 deletions(-) diff --git a/arch/arm26/mm/fault.c b/arch/arm26/mm/fault.c index dacca8bb7744..bd6f2db608b7 100644 --- a/arch/arm26/mm/fault.c +++ b/arch/arm26/mm/fault.c @@ -176,12 +176,12 @@ survive: * Handle the "normal" cases first - successful and sigbus */ switch (fault) { - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; return fault; - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; - case 0: + case VM_FAULT_SIGBUS: return fault; } @@ -226,14 +226,11 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) /* * Handle the "normal" case first */ - if (fault > 0) + switch (fault) { + case VM_FAULT_MINOR: + case VM_FAULT_MAJOR: return 0; - - /* - * We had some memory, but were unable to - * successfully fix up this page fault. - */ - if (fault == 0){ + case VM_FAULT_SIGBUS: goto do_sigbus; } diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index fe1cc36b5aca..934c51078cce 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c @@ -284,13 +284,13 @@ do_page_fault(unsigned long address, struct pt_regs *regs, */ switch (handle_mm_fault(mm, vma, address, writeaccess & 1)) { - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; default: goto out_of_memory; diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c index 41d02ac48233..8b3eb50c5105 100644 --- a/arch/frv/mm/fault.c +++ b/arch/frv/mm/fault.c @@ -163,13 +163,13 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear * the fault. */ switch (handle_mm_fault(mm, vma, ear0, write)) { - case 1: + case VM_FAULT_MINOR: current->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: current->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; default: goto out_of_memory; diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index ac48b6d2aff6..aec15270d334 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -160,13 +160,13 @@ good_area: printk("handle_mm_fault returns %d\n",fault); #endif switch (fault) { - case 1: + case VM_FAULT_MINOR: current->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: current->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto bus_err; default: goto out_of_memory; diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index eaa701479f5f..0ad945d4c0a4 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -178,17 +178,17 @@ good_area: */ switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) { - case 1: + case VM_FAULT_MINOR: ++current->min_flt; break; - case 2: + case VM_FAULT_MAJOR: ++current->maj_flt; break; - case 0: + case VM_FAULT_SIGBUS: /* - * We ran out of memory, or some other thing happened - * to us that made us unable to handle the page fault - * gracefully. + * We hit a hared mapping outside of the file, or some + * other thing happened to us that made us unable to + * handle the page fault gracefully. */ goto bad_area; default: diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c index a24932881dbb..f08d0eaf6497 100644 --- a/arch/sh64/mm/fault.c +++ b/arch/sh64/mm/fault.c @@ -223,13 +223,13 @@ good_area: */ survive: switch (handle_mm_fault(mm, vma, address, writeaccess)) { - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; default: goto out_of_memory; -- cgit v1.2.3 From fdd0edf2aca72e374d10e7a0957a006f18bffaf4 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 4 Aug 2005 13:28:40 -0500 Subject: [SCSI] fix aic7xxx performance issues since 2.6.12-rc2 Several people noticed we dropped quite a bit on benchmark figures. OK, it was my fault but unfortunately I discovered I ran out of brown paper bags a while ago and forgot to reorder them. The issue is that a construct introduced in the conversion of the driver to use the transport class keyed off whether the block request was tagged or not. However, the aic7xxx driver doesn't properly set up the block layer TCQ (it uses the wrong API), so the driver now things all requests are untagged and we keep it to a queue depth of a single element. Oops. The fix is to use the correct TCQ API. Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx_osm.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index d79a2ae89979..687f19e9cf03 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1264,14 +1264,12 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, } switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) { case AHC_DEV_Q_BASIC: - scsi_adjust_queue_depth(sdev, - MSG_SIMPLE_TASK, - dev->openings + dev->active); + scsi_set_tag_type(sdev, MSG_SIMPLE_TAG); + scsi_activate_tcq(sdev, dev->openings + dev->active); break; case AHC_DEV_Q_TAGGED: - scsi_adjust_queue_depth(sdev, - MSG_ORDERED_TASK, - dev->openings + dev->active); + scsi_set_tag_type(sdev, MSG_ORDERED_TAG); + scsi_activate_tcq(sdev, dev->openings + dev->active); break; default: /* @@ -1280,9 +1278,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, * serially on the controller/device. This should * remove some latency. */ - scsi_adjust_queue_depth(sdev, - /*NON-TAGGED*/0, - /*queue depth*/2); + scsi_deactivate_tcq(sdev, 2); break; } } -- cgit v1.2.3 From c80f90ba15ed56ae36d1fb51f81a88f9ba0d8c8b Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Thu, 4 Aug 2005 20:43:40 +0100 Subject: [PATCH] ARM: 2844/1: Add maintainer for Jornada 720 Patch from Michael Gernoth As discussed on the handhelds.org Jornada mailinglist, I take over maintainership of the currently unmaintained Jornada 720-port in the mainline kernel. Signed-off-by: Michael Gernoth Signed-off-by: Russell King --- arch/arm/mach-sa1100/jornada720.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index eee3cbc5ec4f..2f497112c96a 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c @@ -97,6 +97,7 @@ static void __init jornada720_map_io(void) } MACHINE_START(JORNADA720, "HP Jornada 720") + /* Maintainer: Michael Gernoth */ .phys_ram = 0xc0000000, .phys_io = 0x80000000, .io_pg_offst = ((0xf8000000) >> 18) & 0xfffc, -- cgit v1.2.3 From 556e58febf90c8cb1da25669d0892bf5fd2ddac2 Mon Sep 17 00:00:00 2001 From: Ravikiran G Thirumalai Date: Thu, 4 Aug 2005 12:53:26 -0700 Subject: [PATCH] ide: fix kmalloc_node breakage in ide driver Patch fixes oops caused by ide interfaces not on pci. pcibus_to_node causes the kernel to crash otherwise. Patch also adds a BUG_ON to check if hwif is NULL. Signed-off-by: Christoph Lameter Signed-off-by: Shai Fultheim Signed-off-by: Ravikiran Thirumalai Cc: Andi Kleen Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-probe.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 7df85af75371..94daf40ae323 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -960,6 +960,15 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) } #endif /* MAX_HWIFS > 1 */ +static inline int hwif_to_node(ide_hwif_t *hwif) +{ + if (hwif->pci_dev) + return pcibus_to_node(hwif->pci_dev->bus); + else + /* Add ways to determine the node of other busses here */ + return -1; +} + /* * init request queue */ @@ -978,8 +987,7 @@ static int ide_init_queue(ide_drive_t *drive) * do not. */ - q = blk_init_queue_node(do_ide_request, &ide_lock, - pcibus_to_node(drive->hwif->pci_dev->bus)); + q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif)); if (!q) return 1; @@ -1048,6 +1056,8 @@ static int init_irq (ide_hwif_t *hwif) BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); + BUG_ON(hwif == NULL); + down(&ide_cfg_sem); hwif->hwgroup = NULL; #if MAX_HWIFS > 1 @@ -1097,7 +1107,7 @@ static int init_irq (ide_hwif_t *hwif) spin_unlock_irq(&ide_lock); } else { hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL, - pcibus_to_node(hwif->drives[0].hwif->pci_dev->bus)); + hwif_to_node(hwif->drives[0].hwif)); if (!hwgroup) goto out_up; -- cgit v1.2.3 From 75eedfed3e2d05563f44d2f69efb991fad95d7f1 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Thu, 4 Aug 2005 12:53:29 -0700 Subject: [PATCH] ppc64: Fix UP kernel build CONFIG_KEXEC breaks UP builds because of a misspelled smp_release_cpus(). Also, the function isn't defined unless built with CONFIG_SMP but it is needed if we are to go from a UP to SMP kernel. Enable it and document it. Thanks to Steven Winiecki for reporting this and to Milton for remembering how it's supposed to work and why. Signed-off-by: Olof Johansson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/head.S | 2 +- arch/ppc64/kernel/machine_kexec.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 74fc3bc68604..784f56d4684c 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -2071,7 +2071,7 @@ _GLOBAL(hmt_start_secondary) blr #endif -#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) +#if defined(CONFIG_KEXEC) || (defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)) _GLOBAL(smp_release_cpus) /* All secondary cpus are spinning on a common * spinloop, release them all now so they can start diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c index fdb2fc649d72..5c40bb6788df 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/ppc64/kernel/machine_kexec.c @@ -243,13 +243,17 @@ static void kexec_prepare_cpus(void) static void kexec_prepare_cpus(void) { + extern void smp_release_cpus(void); /* * move the secondarys to us so that we can copy * the new kernel 0-0x100 safely * * do this if kexec in setup.c ? + * + * We need to release the cpus if we are ever going from an + * UP to an SMP kernel. */ - smp_relase_cpus(); + smp_release_cpus(); if (ppc_md.cpu_irq_down) ppc_md.cpu_irq_down(); local_irq_disable(); -- cgit v1.2.3 From 4dcef52400fa6b9eb2de589300ae0151a1c65b3b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Aug 2005 12:53:30 -0700 Subject: [PATCH] v4l: oopsfix for BTTV on badly behaved PCI chipsets no_overlay bttv parameter implemented to fix OOPS on some PCI chipsets (like some VIA) with these behaviors: 1) If pci_quicks does identify the chip as having troubles to handle PCI2PCI transfers, no_overlay defaults to 1. The user may force it to 0, to reenable (not recommended). 2) For newer chipsets not blacklisted, no_overlay=1 is provided as a workaround until PCI chipset included on /drivers/pci/quirks.c Thanks to Bodo Eggert <7eggert@gmx.de> Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/bttv/Insmod-options | 3 +++ drivers/media/video/bttv-cards.c | 8 +++++--- drivers/media/video/bttv-driver.c | 28 +++++++++++++++++++++++---- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Documentation/video4linux/bttv/Insmod-options b/Documentation/video4linux/bttv/Insmod-options index 7bb5a50b0779..fc94ff235ffa 100644 --- a/Documentation/video4linux/bttv/Insmod-options +++ b/Documentation/video4linux/bttv/Insmod-options @@ -44,6 +44,9 @@ bttv.o push used by bttv. bttv will disable overlay by default on this hardware to avoid crashes. With this insmod option you can override this. + no_overlay=1 Disable overlay. It should be used by broken + hardware that doesn't support PCI2PCI direct + transfers. automute=0/1 Automatically mutes the sound if there is no TV signal, on by default. You might try to disable this if you have bad input signal diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 6c52fd0bb7df..a97b9b958ed6 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -95,7 +95,7 @@ static int __devinit pvr_boot(struct bttv *btv); static unsigned int triton1=0; static unsigned int vsfx=0; static unsigned int latency = UNSET; -static unsigned int no_overlay=-1; +int no_overlay=-1; static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; @@ -4296,9 +4296,11 @@ void __devinit bttv_check_chipset(void) printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n"); if (pcipci_fail) { printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n"); - if (UNSET == no_overlay) { - printk(KERN_WARNING "bttv: going to disable overlay.\n"); + if (!no_overlay) { + printk(KERN_WARNING "bttv: overlay will be disabled.\n"); no_overlay = 1; + } else { + printk(KERN_WARNING "bttv: overlay forced. Use this option at your own risk.\n"); } } if (UNSET != latency) diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 67f331eeeb19..eee9322ce21b 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1,5 +1,5 @@ /* - $Id: bttv-driver.c,v 1.45 2005/07/20 19:43:24 mkrufky Exp $ + $Id: bttv-driver.c,v 1.52 2005/08/04 00:55:16 mchehab Exp $ bttv - Bt848 frame grabber driver @@ -80,6 +80,7 @@ static unsigned int irq_iswitch = 0; static unsigned int uv_ratio = 50; static unsigned int full_luma_range = 0; static unsigned int coring = 0; +extern int no_overlay; /* API features (turn on/off stuff for testing) */ static unsigned int v4l2 = 1; @@ -2151,6 +2152,10 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, return 0; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (no_overlay > 0) { + printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; + } return setup_window(fh, btv, &f->fmt.win, 1); case V4L2_BUF_TYPE_VBI_CAPTURE: retval = bttv_switch_type(fh,f->type); @@ -2224,9 +2229,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, /* others */ cap->type = VID_TYPE_CAPTURE| VID_TYPE_TUNER| - VID_TYPE_OVERLAY| VID_TYPE_CLIPPING| VID_TYPE_SCALES; + if (no_overlay <= 0) + cap->type |= VID_TYPE_OVERLAY; + cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; cap->minwidth = 48; @@ -2302,6 +2309,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, struct video_window *win = arg; struct v4l2_window w2; + if (no_overlay > 0) { + printk ("VIDIOCSWIN: no_overlay\n"); + return -EINVAL; + } + w2.field = V4L2_FIELD_ANY; w2.w.left = win->x; w2.w.top = win->y; @@ -2577,10 +2589,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, cap->version = BTTV_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (no_overlay <= 0) + cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; + if (bttv_tvcards[btv->c.type].tuner != UNSET && bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) cap->capabilities |= V4L2_CAP_TUNER; @@ -3076,7 +3090,7 @@ static struct file_operations bttv_fops = static struct video_device bttv_video_template = { .name = "UNSET", - .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| + .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = VID_HARDWARE_BT848, .fops = &bttv_fops, @@ -3756,6 +3770,12 @@ static void bttv_unregister_video(struct bttv *btv) /* register video4linux devices */ static int __devinit bttv_register_video(struct bttv *btv) { + if (no_overlay <= 0) { + bttv_video_template.type |= VID_TYPE_OVERLAY; + } else { + printk("bttv: Overlay support disabled.\n"); + } + /* video */ btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); if (NULL == btv->video_dev) -- cgit v1.2.3 From efd8be2a4280f334be9309fa4ca1fb8f4e29475d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 4 Aug 2005 12:53:32 -0700 Subject: [PATCH] md: remove a stray debugging printk. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 6580e0fa4a47..08f003aa6cd7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3484,7 +3484,6 @@ static void md_do_sync(mddev_t *mddev) goto skip; } ITERATE_MDDEV(mddev2,tmp) { - printk("."); if (mddev2 == mddev) continue; if (mddev2->curr_resync && -- cgit v1.2.3 From aa1595e9f3d0d731bcfc6c2680d5483b78f663dc Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 4 Aug 2005 12:53:32 -0700 Subject: [PATCH] md: make 'md' and alias for 'md-mod' Until the bitmap code was added, modprobe md would load the md module. But now the md module is called 'md-mod', so we really need an alias for backwards comparability. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index 08f003aa6cd7..9fd4dbea0d0d 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4006,3 +4006,4 @@ EXPORT_SYMBOL(md_wakeup_thread); EXPORT_SYMBOL(md_print_devices); EXPORT_SYMBOL(md_check_recovery); MODULE_LICENSE("GPL"); +MODULE_ALIAS("md"); -- cgit v1.2.3 From 193f1c931517592ec4188d15bf261e4bff368207 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 4 Aug 2005 12:53:33 -0700 Subject: [PATCH] md: always honour md bitmap being read from disk The code currently will ignore the bitmap if the array seem to be in-sync. This is wrong if the array is degraded, and probably wrong anyway. If the bitmap says some chunks are not in in-sync, and the superblock says everything IS in sync, then something is clearly wrong, and it is safer to trust the bitmap. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 52 +++++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 70bca955e0de..09d32db06d20 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -818,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap) return 0; } -static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, - unsigned long sectors, int in_sync); +static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset); /* * bitmap_init_from_disk -- called at bitmap_create time to initialize * the in-memory bitmap from the on-disk bitmap -- also, sets up the * memory mapping of the bitmap file @@ -828,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, * previously kicked from the array, we mark all the bits as * 1's in order to cause a full resync. */ -static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) +static int bitmap_init_from_disk(struct bitmap *bitmap) { unsigned long i, chunks, index, oldindex, bit; struct page *page = NULL, *oldpage = NULL; @@ -929,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) } if (test_bit(bit, page_address(page))) { /* if the disk bit is set, set the memory bit */ - bitmap_set_memory_bits(bitmap, - i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync); + bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap)); bit_cnt++; } } @@ -1426,35 +1424,30 @@ void bitmap_close_sync(struct bitmap *bitmap) } } -static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, - unsigned long sectors, int in_sync) +static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset) { /* For each chunk covered by any of these sectors, set the - * counter to 1 and set resync_needed unless in_sync. They should all + * counter to 1 and set resync_needed. They should all * be 0 at this point */ - while (sectors) { - int secs; - bitmap_counter_t *bmc; - spin_lock_irq(&bitmap->lock); - bmc = bitmap_get_counter(bitmap, offset, &secs, 1); - if (!bmc) { - spin_unlock_irq(&bitmap->lock); - return; - } - if (! *bmc) { - struct page *page; - *bmc = 1 | (in_sync? 0 : NEEDED_MASK); - bitmap_count_page(bitmap, offset, 1); - page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); - set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); - } + + int secs; + bitmap_counter_t *bmc; + spin_lock_irq(&bitmap->lock); + bmc = bitmap_get_counter(bitmap, offset, &secs, 1); + if (!bmc) { spin_unlock_irq(&bitmap->lock); - if (sectors > secs) - sectors -= secs; - else - sectors = 0; + return; } + if (! *bmc) { + struct page *page; + *bmc = 1 | NEEDED_MASK; + bitmap_count_page(bitmap, offset, 1); + page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)); + set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); + } + spin_unlock_irq(&bitmap->lock); + } /* @@ -1565,7 +1558,8 @@ int bitmap_create(mddev_t *mddev) /* now that we have some pages available, initialize the in-memory * bitmap from the on-disk bitmap */ - err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector); + err = bitmap_init_from_disk(bitmap); + if (err) return err; -- cgit v1.2.3 From e3b9703e27aab3839dcdb76b00d98428b67d25b0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 4 Aug 2005 12:53:34 -0700 Subject: [PATCH] md: yet another attempt to get bitmap-based resync to do the right thing in all cases... Firstly, R1BIO_Degraded was being set in a number of places in the resync code, but is never used there, so get rid of those settings. Then: When doing a resync, we want to clear the bit in the bitmap iff the array will be non-degraded when the sync has completed. However the current code would clear the bitmap if the array was non-degraded when the resync *started*, which obviously isn't right (it is for 'resync' but not for 'recovery' - i.e. rebuilding a failed drive). This patch calculated 'still_degraded' and uses the to tell bitmap_start_sync whether this sync should clear the corresponding bit. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid1.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d3a64a04a6d8..51d9645ed09c 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -893,7 +893,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) if (!uptodate) { md_error(r1_bio->mddev, conf->mirrors[r1_bio->read_disk].rdev); - set_bit(R1BIO_Degraded, &r1_bio->state); } else set_bit(R1BIO_Uptodate, &r1_bio->state); rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev); @@ -918,10 +917,9 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) mirror = i; break; } - if (!uptodate) { + if (!uptodate) md_error(mddev, conf->mirrors[mirror].rdev); - set_bit(R1BIO_Degraded, &r1_bio->state); - } + update_head_pos(mirror, r1_bio); if (atomic_dec_and_test(&r1_bio->remaining)) { @@ -1109,6 +1107,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i int i; int write_targets = 0; int sync_blocks; + int still_degraded = 0; if (!conf->r1buf_pool) { @@ -1137,7 +1136,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i return 0; } - if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, mddev->degraded) && + /* before building a request, check if we can skip these blocks.. + * This call the bitmap_start_sync doesn't actually record anything + */ + if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) && !conf->fullsync) { /* We can skip this block, and probably several more */ *skipped = 1; @@ -1203,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i if (i == disk) { bio->bi_rw = READ; bio->bi_end_io = end_sync_read; - } else if (conf->mirrors[i].rdev && - !conf->mirrors[i].rdev->faulty && - (!conf->mirrors[i].rdev->in_sync || - sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) { + } else if (conf->mirrors[i].rdev == NULL || + conf->mirrors[i].rdev->faulty) { + still_degraded = 1; + continue; + } else if (!conf->mirrors[i].rdev->in_sync || + sector_nr + RESYNC_SECTORS > mddev->recovery_cp) { bio->bi_rw = WRITE; bio->bi_end_io = end_sync_write; write_targets ++; } else + /* no need to read or write here */ continue; bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset; bio->bi_bdev = conf->mirrors[i].rdev->bdev; bio->bi_private = r1_bio; } - if (write_targets + 1 < conf->raid_disks) - /* array degraded, can't clear bitmap */ - set_bit(R1BIO_Degraded, &r1_bio->state); - if (write_targets == 0) { /* There is nowhere to write, so all non-sync * drives must be failed - so we are finished @@ -1243,7 +1244,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i break; if (sync_blocks == 0) { if (!bitmap_start_sync(mddev->bitmap, sector_nr, - &sync_blocks, mddev->degraded) && + &sync_blocks, still_degraded) && !conf->fullsync) break; if (sync_blocks < (PAGE_SIZE>>9)) -- cgit v1.2.3 From 6b8b3e8a8b3e62b4209eaa36697e3c9df457e196 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 4 Aug 2005 12:53:35 -0700 Subject: [PATCH] md: make sure md bitmap updates are flushed when array is stopped. The recent change to never ignore the bitmap, revealed that the bitmap isn't begin flushed properly when an array is stopped. We call bitmap_daemon_work three times as there is a three-stage pipeline for flushing updates to the bitmap file. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 23 +++++++++++++++++++++++ drivers/md/md.c | 2 ++ include/linux/raid/bitmap.h | 1 + 3 files changed, 26 insertions(+) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 09d32db06d20..41df4cda66e2 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1450,6 +1450,29 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset) } +/* + * flush out any pending updates + */ +void bitmap_flush(mddev_t *mddev) +{ + struct bitmap *bitmap = mddev->bitmap; + int sleep; + + if (!bitmap) /* there was no bitmap */ + return; + + /* run the daemon_work three time to ensure everything is flushed + * that can be + */ + sleep = bitmap->daemon_sleep; + bitmap->daemon_sleep = 0; + bitmap_daemon_work(bitmap); + bitmap_daemon_work(bitmap); + bitmap_daemon_work(bitmap); + bitmap->daemon_sleep = sleep; + bitmap_update_sb(bitmap); +} + /* * free memory that was allocated */ diff --git a/drivers/md/md.c b/drivers/md/md.c index 9fd4dbea0d0d..480f658db6f2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1798,6 +1798,8 @@ static int do_md_stop(mddev_t * mddev, int ro) goto out; mddev->ro = 1; } else { + bitmap_flush(mddev); + wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); if (mddev->ro) set_disk_ro(disk, 0); blk_queue_make_request(mddev->queue, md_fail_request); diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h index 6213e976eade..4bf1659f8aa8 100644 --- a/include/linux/raid/bitmap.h +++ b/include/linux/raid/bitmap.h @@ -248,6 +248,7 @@ struct bitmap { /* these are used only by md/bitmap */ int bitmap_create(mddev_t *mddev); +void bitmap_flush(mddev_t *mddev); void bitmap_destroy(mddev_t *mddev); int bitmap_active(struct bitmap *bitmap); -- cgit v1.2.3 From d27a4dddd96f4ee898f8d1d597d38f8f4079bbb0 Mon Sep 17 00:00:00 2001 From: Jim Keniston Date: Thu, 4 Aug 2005 12:53:35 -0700 Subject: [PATCH] Add Documentation/kprobes.txt Acked-by: Prasanna S Panchamukhi Signed-off-by: Jim Keniston Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/kprobes.txt | 588 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 588 insertions(+) create mode 100644 Documentation/kprobes.txt diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt new file mode 100644 index 000000000000..0541fe1de704 --- /dev/null +++ b/Documentation/kprobes.txt @@ -0,0 +1,588 @@ +Title : Kernel Probes (Kprobes) +Authors : Jim Keniston + : Prasanna S Panchamukhi + +CONTENTS + +1. Concepts: Kprobes, Jprobes, Return Probes +2. Architectures Supported +3. Configuring Kprobes +4. API Reference +5. Kprobes Features and Limitations +6. Probe Overhead +7. TODO +8. Kprobes Example +9. Jprobes Example +10. Kretprobes Example + +1. Concepts: Kprobes, Jprobes, Return Probes + +Kprobes enables you to dynamically break into any kernel routine and +collect debugging and performance information non-disruptively. You +can trap at almost any kernel code address, specifying a handler +routine to be invoked when the breakpoint is hit. + +There are currently three types of probes: kprobes, jprobes, and +kretprobes (also called return probes). A kprobe can be inserted +on virtually any instruction in the kernel. A jprobe is inserted at +the entry to a kernel function, and provides convenient access to the +function's arguments. A return probe fires when a specified function +returns. + +In the typical case, Kprobes-based instrumentation is packaged as +a kernel module. The module's init function installs ("registers") +one or more probes, and the exit function unregisters them. A +registration function such as register_kprobe() specifies where +the probe is to be inserted and what handler is to be called when +the probe is hit. + +The next three subsections explain how the different types of +probes work. They explain certain things that you'll need to +know in order to make the best use of Kprobes -- e.g., the +difference between a pre_handler and a post_handler, and how +to use the maxactive and nmissed fields of a kretprobe. But +if you're in a hurry to start using Kprobes, you can skip ahead +to section 2. + +1.1 How Does a Kprobe Work? + +When a kprobe is registered, Kprobes makes a copy of the probed +instruction and replaces the first byte(s) of the probed instruction +with a breakpoint instruction (e.g., int3 on i386 and x86_64). + +When a CPU hits the breakpoint instruction, a trap occurs, the CPU's +registers are saved, and control passes to Kprobes via the +notifier_call_chain mechanism. Kprobes executes the "pre_handler" +associated with the kprobe, passing the handler the addresses of the +kprobe struct and the saved registers. + +Next, Kprobes single-steps its copy of the probed instruction. +(It would be simpler to single-step the actual instruction in place, +but then Kprobes would have to temporarily remove the breakpoint +instruction. This would open a small time window when another CPU +could sail right past the probepoint.) + +After the instruction is single-stepped, Kprobes executes the +"post_handler," if any, that is associated with the kprobe. +Execution then continues with the instruction following the probepoint. + +1.2 How Does a Jprobe Work? + +A jprobe is implemented using a kprobe that is placed on a function's +entry point. It employs a simple mirroring principle to allow +seamless access to the probed function's arguments. The jprobe +handler routine should have the same signature (arg list and return +type) as the function being probed, and must always end by calling +the Kprobes function jprobe_return(). + +Here's how it works. When the probe is hit, Kprobes makes a copy of +the saved registers and a generous portion of the stack (see below). +Kprobes then points the saved instruction pointer at the jprobe's +handler routine, and returns from the trap. As a result, control +passes to the handler, which is presented with the same register and +stack contents as the probed function. When it is done, the handler +calls jprobe_return(), which traps again to restore the original stack +contents and processor state and switch to the probed function. + +By convention, the callee owns its arguments, so gcc may produce code +that unexpectedly modifies that portion of the stack. This is why +Kprobes saves a copy of the stack and restores it after the jprobe +handler has run. Up to MAX_STACK_SIZE bytes are copied -- e.g., +64 bytes on i386. + +Note that the probed function's args may be passed on the stack +or in registers (e.g., for x86_64 or for an i386 fastcall function). +The jprobe will work in either case, so long as the handler's +prototype matches that of the probed function. + +1.3 How Does a Return Probe Work? + +When you call register_kretprobe(), Kprobes establishes a kprobe at +the entry to the function. When the probed function is called and this +probe is hit, Kprobes saves a copy of the return address, and replaces +the return address with the address of a "trampoline." The trampoline +is an arbitrary piece of code -- typically just a nop instruction. +At boot time, Kprobes registers a kprobe at the trampoline. + +When the probed function executes its return instruction, control +passes to the trampoline and that probe is hit. Kprobes' trampoline +handler calls the user-specified handler associated with the kretprobe, +then sets the saved instruction pointer to the saved return address, +and that's where execution resumes upon return from the trap. + +While the probed function is executing, its return address is +stored in an object of type kretprobe_instance. Before calling +register_kretprobe(), the user sets the maxactive field of the +kretprobe struct to specify how many instances of the specified +function can be probed simultaneously. register_kretprobe() +pre-allocates the indicated number of kretprobe_instance objects. + +For example, if the function is non-recursive and is called with a +spinlock held, maxactive = 1 should be enough. If the function is +non-recursive and can never relinquish the CPU (e.g., via a semaphore +or preemption), NR_CPUS should be enough. If maxactive <= 0, it is +set to a default value. If CONFIG_PREEMPT is enabled, the default +is max(10, 2*NR_CPUS). Otherwise, the default is NR_CPUS. + +It's not a disaster if you set maxactive too low; you'll just miss +some probes. In the kretprobe struct, the nmissed field is set to +zero when the return probe is registered, and is incremented every +time the probed function is entered but there is no kretprobe_instance +object available for establishing the return probe. + +2. Architectures Supported + +Kprobes, jprobes, and return probes are implemented on the following +architectures: + +- i386 +- x86_64 (AMD-64, E64MT) +- ppc64 +- ia64 (Support for probes on certain instruction types is still in progress.) +- sparc64 (Return probes not yet implemented.) + +3. Configuring Kprobes + +When configuring the kernel using make menuconfig/xconfig/oldconfig, +ensure that CONFIG_KPROBES is set to "y". Under "Kernel hacking", +look for "Kprobes". You may have to enable "Kernel debugging" +(CONFIG_DEBUG_KERNEL) before you can enable Kprobes. + +You may also want to ensure that CONFIG_KALLSYMS and perhaps even +CONFIG_KALLSYMS_ALL are set to "y", since kallsyms_lookup_name() +is a handy, version-independent way to find a function's address. + +If you need to insert a probe in the middle of a function, you may find +it useful to "Compile the kernel with debug info" (CONFIG_DEBUG_INFO), +so you can use "objdump -d -l vmlinux" to see the source-to-object +code mapping. + +4. API Reference + +The Kprobes API includes a "register" function and an "unregister" +function for each type of probe. Here are terse, mini-man-page +specifications for these functions and the associated probe handlers +that you'll write. See the latter half of this document for examples. + +4.1 register_kprobe + +#include +int register_kprobe(struct kprobe *kp); + +Sets a breakpoint at the address kp->addr. When the breakpoint is +hit, Kprobes calls kp->pre_handler. After the probed instruction +is single-stepped, Kprobe calls kp->post_handler. If a fault +occurs during execution of kp->pre_handler or kp->post_handler, +or during single-stepping of the probed instruction, Kprobes calls +kp->fault_handler. Any or all handlers can be NULL. + +register_kprobe() returns 0 on success, or a negative errno otherwise. + +User's pre-handler (kp->pre_handler): +#include +#include +int pre_handler(struct kprobe *p, struct pt_regs *regs); + +Called with p pointing to the kprobe associated with the breakpoint, +and regs pointing to the struct containing the registers saved when +the breakpoint was hit. Return 0 here unless you're a Kprobes geek. + +User's post-handler (kp->post_handler): +#include +#include +void post_handler(struct kprobe *p, struct pt_regs *regs, + unsigned long flags); + +p and regs are as described for the pre_handler. flags always seems +to be zero. + +User's fault-handler (kp->fault_handler): +#include +#include +int fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr); + +p and regs are as described for the pre_handler. trapnr is the +architecture-specific trap number associated with the fault (e.g., +on i386, 13 for a general protection fault or 14 for a page fault). +Returns 1 if it successfully handled the exception. + +4.2 register_jprobe + +#include +int register_jprobe(struct jprobe *jp) + +Sets a breakpoint at the address jp->kp.addr, which must be the address +of the first instruction of a function. When the breakpoint is hit, +Kprobes runs the handler whose address is jp->entry. + +The handler should have the same arg list and return type as the probed +function; and just before it returns, it must call jprobe_return(). +(The handler never actually returns, since jprobe_return() returns +control to Kprobes.) If the probed function is declared asmlinkage, +fastcall, or anything else that affects how args are passed, the +handler's declaration must match. + +register_jprobe() returns 0 on success, or a negative errno otherwise. + +4.3 register_kretprobe + +#include +int register_kretprobe(struct kretprobe *rp); + +Establishes a return probe for the function whose address is +rp->kp.addr. When that function returns, Kprobes calls rp->handler. +You must set rp->maxactive appropriately before you call +register_kretprobe(); see "How Does a Return Probe Work?" for details. + +register_kretprobe() returns 0 on success, or a negative errno +otherwise. + +User's return-probe handler (rp->handler): +#include +#include +int kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs); + +regs is as described for kprobe.pre_handler. ri points to the +kretprobe_instance object, of which the following fields may be +of interest: +- ret_addr: the return address +- rp: points to the corresponding kretprobe object +- task: points to the corresponding task struct +The handler's return value is currently ignored. + +4.4 unregister_*probe + +#include +void unregister_kprobe(struct kprobe *kp); +void unregister_jprobe(struct jprobe *jp); +void unregister_kretprobe(struct kretprobe *rp); + +Removes the specified probe. The unregister function can be called +at any time after the probe has been registered. + +5. Kprobes Features and Limitations + +As of Linux v2.6.12, Kprobes allows multiple probes at the same +address. Currently, however, there cannot be multiple jprobes on +the same function at the same time. + +In general, you can install a probe anywhere in the kernel. +In particular, you can probe interrupt handlers. Known exceptions +are discussed in this section. + +For obvious reasons, it's a bad idea to install a probe in +the code that implements Kprobes (mostly kernel/kprobes.c and +arch/*/kernel/kprobes.c). A patch in the v2.6.13 timeframe instructs +Kprobes to reject such requests. + +If you install a probe in an inline-able function, Kprobes makes +no attempt to chase down all inline instances of the function and +install probes there. gcc may inline a function without being asked, +so keep this in mind if you're not seeing the probe hits you expect. + +A probe handler can modify the environment of the probed function +-- e.g., by modifying kernel data structures, or by modifying the +contents of the pt_regs struct (which are restored to the registers +upon return from the breakpoint). So Kprobes can be used, for example, +to install a bug fix or to inject faults for testing. Kprobes, of +course, has no way to distinguish the deliberately injected faults +from the accidental ones. Don't drink and probe. + +Kprobes makes no attempt to prevent probe handlers from stepping on +each other -- e.g., probing printk() and then calling printk() from a +probe handler. As of Linux v2.6.12, if a probe handler hits a probe, +that second probe's handlers won't be run in that instance. + +In Linux v2.6.12 and previous versions, Kprobes' data structures are +protected by a single lock that is held during probe registration and +unregistration and while handlers are run. Thus, no two handlers +can run simultaneously. To improve scalability on SMP systems, +this restriction will probably be removed soon, in which case +multiple handlers (or multiple instances of the same handler) may +run concurrently on different CPUs. Code your handlers accordingly. + +Kprobes does not use semaphores or allocate memory except during +registration and unregistration. + +Probe handlers are run with preemption disabled. Depending on the +architecture, handlers may also run with interrupts disabled. In any +case, your handler should not yield the CPU (e.g., by attempting to +acquire a semaphore). + +Since a return probe is implemented by replacing the return +address with the trampoline's address, stack backtraces and calls +to __builtin_return_address() will typically yield the trampoline's +address instead of the real return address for kretprobed functions. +(As far as we can tell, __builtin_return_address() is used only +for instrumentation and error reporting.) + +If the number of times a function is called does not match the +number of times it returns, registering a return probe on that +function may produce undesirable results. We have the do_exit() +and do_execve() cases covered. do_fork() is not an issue. We're +unaware of other specific cases where this could be a problem. + +6. Probe Overhead + +On a typical CPU in use in 2005, a kprobe hit takes 0.5 to 1.0 +microseconds to process. Specifically, a benchmark that hits the same +probepoint repeatedly, firing a simple handler each time, reports 1-2 +million hits per second, depending on the architecture. A jprobe or +return-probe hit typically takes 50-75% longer than a kprobe hit. +When you have a return probe set on a function, adding a kprobe at +the entry to that function adds essentially no overhead. + +Here are sample overhead figures (in usec) for different architectures. +k = kprobe; j = jprobe; r = return probe; kr = kprobe + return probe +on same function; jr = jprobe + return probe on same function + +i386: Intel Pentium M, 1495 MHz, 2957.31 bogomips +k = 0.57 usec; j = 1.00; r = 0.92; kr = 0.99; jr = 1.40 + +x86_64: AMD Opteron 246, 1994 MHz, 3971.48 bogomips +k = 0.49 usec; j = 0.76; r = 0.80; kr = 0.82; jr = 1.07 + +ppc64: POWER5 (gr), 1656 MHz (SMT disabled, 1 virtual CPU per physical CPU) +k = 0.77 usec; j = 1.31; r = 1.26; kr = 1.45; jr = 1.99 + +7. TODO + +a. SystemTap (http://sourceware.org/systemtap): Work in progress +to provide a simplified programming interface for probe-based +instrumentation. +b. Improved SMP scalability: Currently, work is in progress to handle +multiple kprobes in parallel. +c. Kernel return probes for sparc64. +d. Support for other architectures. +e. User-space probes. + +8. Kprobes Example + +Here's a sample kernel module showing the use of kprobes to dump a +stack trace and selected i386 registers when do_fork() is called. +----- cut here ----- +/*kprobe_example.c*/ +#include +#include +#include +#include +#include + +/*For each probe you need to allocate a kprobe structure*/ +static struct kprobe kp; + +/*kprobe pre_handler: called just before the probed instruction is executed*/ +int handler_pre(struct kprobe *p, struct pt_regs *regs) +{ + printk("pre_handler: p->addr=0x%p, eip=%lx, eflags=0x%lx\n", + p->addr, regs->eip, regs->eflags); + dump_stack(); + return 0; +} + +/*kprobe post_handler: called after the probed instruction is executed*/ +void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags) +{ + printk("post_handler: p->addr=0x%p, eflags=0x%lx\n", + p->addr, regs->eflags); +} + +/* fault_handler: this is called if an exception is generated for any + * instruction within the pre- or post-handler, or when Kprobes + * single-steps the probed instruction. + */ +int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) +{ + printk("fault_handler: p->addr=0x%p, trap #%dn", + p->addr, trapnr); + /* Return 0 because we don't handle the fault. */ + return 0; +} + +int init_module(void) +{ + int ret; + kp.pre_handler = handler_pre; + kp.post_handler = handler_post; + kp.fault_handler = handler_fault; + kp.addr = (kprobe_opcode_t*) kallsyms_lookup_name("do_fork"); + /* register the kprobe now */ + if (!kp.addr) { + printk("Couldn't find %s to plant kprobe\n", "do_fork"); + return -1; + } + if ((ret = register_kprobe(&kp) < 0)) { + printk("register_kprobe failed, returned %d\n", ret); + return -1; + } + printk("kprobe registered\n"); + return 0; +} + +void cleanup_module(void) +{ + unregister_kprobe(&kp); + printk("kprobe unregistered\n"); +} + +MODULE_LICENSE("GPL"); +----- cut here ----- + +You can build the kernel module, kprobe-example.ko, using the following +Makefile: +----- cut here ----- +obj-m := kprobe-example.o +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) +default: + $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules +clean: + rm -f *.mod.c *.ko *.o +----- cut here ----- + +$ make +$ su - +... +# insmod kprobe-example.ko + +You will see the trace data in /var/log/messages and on the console +whenever do_fork() is invoked to create a new process. + +9. Jprobes Example + +Here's a sample kernel module showing the use of jprobes to dump +the arguments of do_fork(). +----- cut here ----- +/*jprobe-example.c */ +#include +#include +#include +#include +#include +#include + +/* + * Jumper probe for do_fork. + * Mirror principle enables access to arguments of the probed routine + * from the probe handler. + */ + +/* Proxy routine having the same arguments as actual do_fork() routine */ +long jdo_fork(unsigned long clone_flags, unsigned long stack_start, + struct pt_regs *regs, unsigned long stack_size, + int __user * parent_tidptr, int __user * child_tidptr) +{ + printk("jprobe: clone_flags=0x%lx, stack_size=0x%lx, regs=0x%p\n", + clone_flags, stack_size, regs); + /* Always end with a call to jprobe_return(). */ + jprobe_return(); + /*NOTREACHED*/ + return 0; +} + +static struct jprobe my_jprobe = { + .entry = (kprobe_opcode_t *) jdo_fork +}; + +int init_module(void) +{ + int ret; + my_jprobe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork"); + if (!my_jprobe.kp.addr) { + printk("Couldn't find %s to plant jprobe\n", "do_fork"); + return -1; + } + + if ((ret = register_jprobe(&my_jprobe)) <0) { + printk("register_jprobe failed, returned %d\n", ret); + return -1; + } + printk("Planted jprobe at %p, handler addr %p\n", + my_jprobe.kp.addr, my_jprobe.entry); + return 0; +} + +void cleanup_module(void) +{ + unregister_jprobe(&my_jprobe); + printk("jprobe unregistered\n"); +} + +MODULE_LICENSE("GPL"); +----- cut here ----- + +Build and insert the kernel module as shown in the above kprobe +example. You will see the trace data in /var/log/messages and on +the console whenever do_fork() is invoked to create a new process. +(Some messages may be suppressed if syslogd is configured to +eliminate duplicate messages.) + +10. Kretprobes Example + +Here's a sample kernel module showing the use of return probes to +report failed calls to sys_open(). +----- cut here ----- +/*kretprobe-example.c*/ +#include +#include +#include +#include + +static const char *probed_func = "sys_open"; + +/* Return-probe handler: If the probed function fails, log the return value. */ +static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + // Substitute the appropriate register name for your architecture -- + // e.g., regs->rax for x86_64, regs->gpr[3] for ppc64. + int retval = (int) regs->eax; + if (retval < 0) { + printk("%s returns %d\n", probed_func, retval); + } + return 0; +} + +static struct kretprobe my_kretprobe = { + .handler = ret_handler, + /* Probe up to 20 instances concurrently. */ + .maxactive = 20 +}; + +int init_module(void) +{ + int ret; + my_kretprobe.kp.addr = + (kprobe_opcode_t *) kallsyms_lookup_name(probed_func); + if (!my_kretprobe.kp.addr) { + printk("Couldn't find %s to plant return probe\n", probed_func); + return -1; + } + if ((ret = register_kretprobe(&my_kretprobe)) < 0) { + printk("register_kretprobe failed, returned %d\n", ret); + return -1; + } + printk("Planted return probe at %p\n", my_kretprobe.kp.addr); + return 0; +} + +void cleanup_module(void) +{ + unregister_kretprobe(&my_kretprobe); + printk("kretprobe unregistered\n"); + /* nmissed > 0 suggests that maxactive was set too low. */ + printk("Missed probing %d instances of %s\n", + my_kretprobe.nmissed, probed_func); +} + +MODULE_LICENSE("GPL"); +----- cut here ----- + +Build and insert the kernel module as shown in the above kprobe +example. You will see the trace data in /var/log/messages and on the +console whenever sys_open() returns a negative value. (Some messages +may be suppressed if syslogd is configured to eliminate duplicate +messages.) + +For additional information on Kprobes, refer to the following URLs: +http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe +http://www.redhat.com/magazine/005mar05/features/kprobes/ -- cgit v1.2.3 From 48f1f5328267f52a34e61b8b0e6fc55a23c1348a Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Thu, 4 Aug 2005 12:53:37 -0700 Subject: [PATCH] dm-raid locking fix This code was never designed to handle more than one instance of do_work() running at once. Signed-Off-By: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-raid1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 12031c9d3f1e..b08df8b9b2ca 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1230,7 +1230,7 @@ static int __init dm_mirror_init(void) if (r) return r; - _kmirrord_wq = create_workqueue("kmirrord"); + _kmirrord_wq = create_singlethread_workqueue("kmirrord"); if (!_kmirrord_wq) { DMERR("couldn't start kmirrord"); dm_dirty_log_exit(); -- cgit v1.2.3 From 6d22d85a852b72398a81b8e476977b28b4400f7c Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 4 Aug 2005 12:53:37 -0700 Subject: [PATCH] ppc64: fix for kexec boot issue The kexec boot is not successful on some power machines since all CPUs are getting removed from global interrupt queue (GIQ) before kexec boot. Some systems always expect at least one CPU in GIQ. Hence, this patch will make sure that only secondary CPUs are removed from GIQ. Signed-off-by: Haren Myneni Signed-off-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/machine_kexec.c | 6 +++--- arch/ppc64/kernel/mpic.c | 4 ++-- arch/ppc64/kernel/mpic.h | 2 +- arch/ppc64/kernel/xics.c | 31 ++++++++++++++++--------------- include/asm-ppc64/machdep.h | 2 +- include/asm-ppc64/xics.h | 2 +- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c index 5c40bb6788df..4775f12a013c 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/ppc64/kernel/machine_kexec.c @@ -185,7 +185,7 @@ void kexec_copy_flush(struct kimage *image) void kexec_smp_down(void *arg) { if (ppc_md.cpu_irq_down) - ppc_md.cpu_irq_down(); + ppc_md.cpu_irq_down(1); local_irq_disable(); kexec_smp_wait(); @@ -232,7 +232,7 @@ static void kexec_prepare_cpus(void) /* after we tell the others to go down */ if (ppc_md.cpu_irq_down) - ppc_md.cpu_irq_down(); + ppc_md.cpu_irq_down(0); put_cpu(); @@ -255,7 +255,7 @@ static void kexec_prepare_cpus(void) */ smp_release_cpus(); if (ppc_md.cpu_irq_down) - ppc_md.cpu_irq_down(); + ppc_md.cpu_irq_down(0); local_irq_disable(); } diff --git a/arch/ppc64/kernel/mpic.c b/arch/ppc64/kernel/mpic.c index e8fbab1df37f..cc262a05ddb4 100644 --- a/arch/ppc64/kernel/mpic.c +++ b/arch/ppc64/kernel/mpic.c @@ -794,10 +794,10 @@ void mpic_setup_this_cpu(void) /* * XXX: someone who knows mpic should check this. - * do we need to eoi the ipi here (see xics comments)? + * do we need to eoi the ipi including for kexec cpu here (see xics comments)? * or can we reset the mpic in the new kernel? */ -void mpic_teardown_this_cpu(void) +void mpic_teardown_this_cpu(int secondary) { struct mpic *mpic = mpic_primary; unsigned long flags; diff --git a/arch/ppc64/kernel/mpic.h b/arch/ppc64/kernel/mpic.h index 99fbbc9a084c..ca78a7f10528 100644 --- a/arch/ppc64/kernel/mpic.h +++ b/arch/ppc64/kernel/mpic.h @@ -256,7 +256,7 @@ extern unsigned int mpic_irq_get_priority(unsigned int irq); extern void mpic_setup_this_cpu(void); /* Clean up for kexec (or cpu offline or ...) */ -extern void mpic_teardown_this_cpu(void); +extern void mpic_teardown_this_cpu(int secondary); /* Request IPIs on primary mpic */ extern void mpic_request_ipis(void); diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index 677c4450984a..d9dc6f28d050 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -647,29 +647,30 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) } } -void xics_teardown_cpu(void) +void xics_teardown_cpu(int secondary) { int cpu = smp_processor_id(); - int status; ops->cppr_info(cpu, 0x00); iosync(); /* - * we need to EOI the IPI if we got here from kexec down IPI - * - * xics doesn't care if we duplicate an EOI as long as we - * don't EOI and raise priority. - * - * probably need to check all the other interrupts too - * should we be flagging idle loop instead? - * or creating some task to be scheduled? + * Some machines need to have at least one cpu in the GIQ, + * so leave the master cpu in the group. */ - ops->xirr_info_set(cpu, XICS_IPI); - - status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, - (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); - WARN_ON(status != 0); + if (secondary) { + /* + * we need to EOI the IPI if we got here from kexec down IPI + * + * probably need to check all the other interrupts too + * should we be flagging idle loop instead? + * or creating some task to be scheduled? + */ + ops->xirr_info_set(cpu, XICS_IPI); + rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, + (1UL << interrupt_server_size) - 1 - + default_distrib_server, 0); + } } #ifdef CONFIG_HOTPLUG_CPU diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h index f0c1d2d92672..f0ef06375947 100644 --- a/include/asm-ppc64/machdep.h +++ b/include/asm-ppc64/machdep.h @@ -84,7 +84,7 @@ struct machdep_calls { void (*init_IRQ)(void); int (*get_irq)(struct pt_regs *); - void (*cpu_irq_down)(void); + void (*cpu_irq_down)(int secondary); /* PCI stuff */ void (*pcibios_fixup)(void); diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h index 0c45e14e26ca..1092af55d707 100644 --- a/include/asm-ppc64/xics.h +++ b/include/asm-ppc64/xics.h @@ -17,7 +17,7 @@ void xics_init_IRQ(void); int xics_get_irq(struct pt_regs *); void xics_setup_cpu(void); -void xics_teardown_cpu(void); +void xics_teardown_cpu(int secondary); void xics_cause_IPI(int cpu); void xics_request_IPIs(void); void xics_migrate_irqs_away(void); -- cgit v1.2.3 From bcf945d36fa0598f41ac4ad46a9dc43135460263 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 4 Aug 2005 13:07:06 -0700 Subject: [PATCH] Error during attempt to join key management session can leave semaphore pinned The attached patch prevents an error during the key session joining operation from hanging future joins in the D state [CAN-2005-2098]. The problem is that the error handling path for the KEYCTL_JOIN_SESSION_KEYRING operation has one error path that doesn't release the session management semaphore. Further attempts to get the semaphore will then sleep for ever in the D state. This can happen in four situations, all involving an attempt to allocate a new session keyring: (1) ENOMEM. (2) The users key quota being reached. (3) A keyring name that is an empty string. (4) A keyring name that is too long. Any user may attempt this operation, and so any user can cause the problem to occur. Signed-Off-By: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/keys/process_keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 9b0369c5a223..c089f78fb94e 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -678,7 +678,7 @@ long join_session_keyring(const char *name) keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); - goto error; + goto error2; } } else if (IS_ERR(keyring)) { -- cgit v1.2.3 From 94efe72f762e2c147d8146d637d5ece5614c8d94 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 4 Aug 2005 13:07:07 -0700 Subject: [PATCH] Destruction of failed keyring oopses The attached patch makes sure that a keyring that failed to instantiate properly is destroyed without oopsing [CAN-2005-2099]. The problem occurs in three stages: (1) The key allocator initialises the type-specific data to all zeroes. In the case of a keyring, this will become a link in the keyring name list when the keyring is instantiated. (2) If a user (any user) attempts to add a keyring with anything other than an empty payload, the keyring instantiation function will fail with an error and won't add the keyring to the name list. (3) The keyring's destructor then sees that the keyring has a description (name) and tries to remove the keyring from the name list, which oopses because the link pointers are both zero. This bug permits any user to take down a box trivially. Signed-Off-By: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/keys/keyring.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index a1f6bac647a1..9c208c756df8 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -201,7 +201,11 @@ static void keyring_destroy(struct key *keyring) if (keyring->description) { write_lock(&keyring_name_lock); - list_del(&keyring->type_data.link); + + if (keyring->type_data.link.next != NULL && + !list_empty(&keyring->type_data.link)) + list_del(&keyring->type_data.link); + write_unlock(&keyring_name_lock); } -- cgit v1.2.3 From 3de11748c1b312833e8a148ab7ec47669ecc99dc Mon Sep 17 00:00:00 2001 From: Robert Love Date: Thu, 4 Aug 2005 13:07:08 -0700 Subject: [PATCH] inotify: update help text The inotify help text still refers to the character device. Update it. Fixes kernel bug #4993. Signed-off-by: Robert Love Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/Kconfig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/Kconfig b/fs/Kconfig index 5d0c4be43dba..e54be7058359 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -363,12 +363,15 @@ config INOTIFY bool "Inotify file change notification support" default y ---help--- - Say Y here to enable inotify support and the /dev/inotify character - device. Inotify is a file change notification system and a + Say Y here to enable inotify support and the associated system + calls. Inotify is a file change notification system and a replacement for dnotify. Inotify fixes numerous shortcomings in dnotify and introduces several new features. It allows monitoring - of both files and directories via a single open fd. Multiple file - events are supported. + of both files and directories via a single open fd. Other features + include multiple file events, one-shot support, and unmount + notification. + + For more information, see Documentation/filesystems/inotify.txt If unsure, say Y. -- cgit v1.2.3 From e234f35c54a30d040313e40833dcf623d14629b4 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Thu, 4 Aug 2005 13:07:08 -0700 Subject: [PATCH] inotify delete race fix The included patch fixes a problem where a inotify client would receive a delete event before the file was actually deleted. The bug affects both dnotify & inotify. Signed-off-by: John McCutchan Signed-off-by: Robert Love Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namei.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 4a27eb798118..83559dce4286 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1801,8 +1801,8 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) } up(&dentry->d_inode->i_sem); if (!error) { - fsnotify_rmdir(dentry, dentry->d_inode, dir); d_delete(dentry); + fsnotify_rmdir(dentry, dentry->d_inode, dir); } dput(dentry); @@ -1874,8 +1874,14 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) /* We don't d_delete() NFS sillyrenamed files--they still exist. */ if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { +#if defined(CONFIG_INOTIFY) || defined(CONFIG_DNOTIFY) + dget(dentry); + d_delete(dentry); fsnotify_unlink(dentry, dir); + dput(dentry); +#else d_delete(dentry); +#endif } return error; -- cgit v1.2.3 From 1c5ad84516ae7ea4ec868436a910a6bd8d20215a Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 4 Aug 2005 13:07:09 -0700 Subject: [PATCH] fix VmSize and VmData after mremap mremap's move_vma is applying __vm_stat_account to the old vma which may have already been freed: move it to just before the do_munmap. mremapping to and fro with CONFIG_DEBUG_SLAB=y showed /proc//status VmSize and VmData wrapping just like in kernel bugzilla #4842, and fixed by this patch - worth including in 2.6.13, though not yet confirmed that it fixes that specific report from Frank van Maarseveen. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mremap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/mremap.c b/mm/mremap.c index ec7238a78f36..fc45dc9a617b 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -229,6 +229,7 @@ static unsigned long move_vma(struct vm_area_struct *vma, * since do_munmap() will decrement it by old_len == new_len */ mm->total_vm += new_len >> PAGE_SHIFT; + __vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT); if (do_munmap(mm, old_addr, old_len) < 0) { /* OOM: unable to split vma, just get accounts right */ @@ -243,7 +244,6 @@ static unsigned long move_vma(struct vm_area_struct *vma, vma->vm_next->vm_flags |= VM_ACCOUNT; } - __vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT); if (vm_flags & VM_LOCKED) { mm->locked_vm += new_len >> PAGE_SHIFT; if (new_len > old_len) -- cgit v1.2.3 From c91096d85c95c6b7fe8d7065e2aa6825e0bdaca9 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 4 Aug 2005 15:36:10 -0700 Subject: [PATCH] remove special HPET_EMULATE_RTC config option We had a user whose apps weren't working correctly because his "rtc" wasn't working fully. For the sake of simplicity, it seems sensible to always enable HPET RTC emulation. Remove a special config option for HPET_EMULATE_RTC and make it directly depend on HPET_TIMER and RTC. This will avoid the hangs when EMULATE_RTC is not configured and when some userlevel script depends on RTC interrupt, as in: http://bugzilla.kernel.org/show_bug.cgi?id=4904 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index a801d9d48606..619d843ba231 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -454,8 +454,9 @@ config HPET_TIMER Choose N to continue using the legacy 8254 timer. config HPET_EMULATE_RTC - bool "Provide RTC interrupt" + bool depends on HPET_TIMER && RTC=y + default y config SMP bool "Symmetric multi-processing support" -- cgit v1.2.3 From e8ed11b9dc07df0134248542ca8e7d40751a6052 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Thu, 4 Aug 2005 13:41:09 -0700 Subject: [PATCH] x86_64: fix 32-bit thread debugging The IA32 ptrace emulation currently returns the wrong registers for fs/gs; it's returning what x86_64 calls gs_base. We need regs.gsindex in order for GDB to correctly locate the TLS area. Without this patch, the 32-bit GDB testsuite bombs on a 64-bit kernel. With it, results look about like I'd expect, although there are still a handful of kernel-related failures (vsyscall related?). Signed-off-by: Daniel Jacobowitz Acked-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/ia32/ptrace32.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index b98b6d2462f6..2a925e2af390 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -43,11 +43,11 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) switch (regno) { case offsetof(struct user32, regs.fs): if (val && (val & 3) != 3) return -EIO; - child->thread.fs = val & 0xffff; + child->thread.fsindex = val & 0xffff; break; case offsetof(struct user32, regs.gs): if (val && (val & 3) != 3) return -EIO; - child->thread.gs = val & 0xffff; + child->thread.gsindex = val & 0xffff; break; case offsetof(struct user32, regs.ds): if (val && (val & 3) != 3) return -EIO; @@ -138,10 +138,10 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) switch (regno) { case offsetof(struct user32, regs.fs): - *val = child->thread.fs; + *val = child->thread.fsindex; break; case offsetof(struct user32, regs.gs): - *val = child->thread.gs; + *val = child->thread.gsindex; break; case offsetof(struct user32, regs.ds): *val = child->thread.ds; -- cgit v1.2.3 From c306895167c8384b88bc02945a0d226a04218fa5 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 4 Aug 2005 16:49:32 -0700 Subject: [PATCH] revert "timer exit cleanup" Revert this June 17 patch: it broke persistence of timers across execve(). Cc: Roland McGrath Cc: george anzinger Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/exit.c | 4 +++- kernel/posix-timers.c | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/exit.c b/kernel/exit.c index 9d1b10ed0135..5b0fb9f09f21 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -829,8 +829,10 @@ fastcall NORET_TYPE void do_exit(long code) acct_update_integrals(tsk); update_mem_hiwater(tsk); group_dead = atomic_dec_and_test(&tsk->signal->live); - if (group_dead) + if (group_dead) { + del_timer_sync(&tsk->signal->real_timer); acct_process(code); + } exit_mm(tsk); exit_sem(tsk); diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 10b2ad749d14..38798a2ff994 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -1166,7 +1166,6 @@ void exit_itimers(struct signal_struct *sig) tmr = list_entry(sig->posix_timers.next, struct k_itimer, list); itimer_delete(tmr); } - del_timer_sync(&sig->real_timer); } /* -- cgit v1.2.3 From fec59a711eef002d4ef9eb8de09dd0a26986eb77 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 4 Aug 2005 18:06:10 -0700 Subject: [PATCH] PCI: restore BAR values after D3hot->D0 for devices that need it Some PCI devices (e.g. 3c905B, 3c556B) lose all configuration (including BARs) when transitioning from D3hot->D0. This leaves such a device in an inaccessible state. The patch below causes the BARs to be restored when enabling such a device, so that its driver will be able to access it. The patch also adds pci_restore_bars as a new global symbol, and adds a correpsonding EXPORT_SYMBOL_GPL for that. Some firmware (e.g. Thinkpad T21) leaves devices in D3hot after a (re)boot. Most drivers call pci_enable_device very early, so devices left in D3hot that lose configuration during the D3hot->D0 transition will be inaccessible to their drivers. Drivers could be modified to account for this, but it would be difficult to know which drivers need modification. This is especially true since often many devices are covered by the same driver. It likely would be necessary to replicate code across dozens of drivers. The patch below should trigger only when transitioning from D3hot->D0 (or at boot), and only for devices that have the "no soft reset" bit cleared in the PM control register. I believe it is safe to include this patch as part of the PCI infrastructure. The cleanest implementation of pci_restore_bars was to call pci_update_resource. Unfortunately, that does not currently exist for the sparc64 architecture. The patch below includes a null implemenation of pci_update_resource for sparc64. Some have expressed interest in making general use of the the pci_restore_bars function, so that has been exported to GPL licensed modules. Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- arch/sparc64/kernel/pci.c | 6 +++++ drivers/pci/pci.c | 59 +++++++++++++++++++++++++++++++++++++++++++---- drivers/pci/setup-res.c | 2 +- include/linux/pci.h | 3 +++ 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index bba140d98b1b..914e125d3971 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -413,6 +413,12 @@ static int pci_assign_bus_resource(const struct pci_bus *bus, return -EBUSY; } +void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) +{ + /* Not implemented for sparc64... */ + BUG(); +} + int pci_assign_resource(struct pci_dev *pdev, int resource) { struct pcidev_cookie *pcp = pdev->sysdata; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1b34fc56067e..65ea7d25f691 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -221,6 +221,37 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) return best; } +/** + * pci_restore_bars - restore a devices BAR values (e.g. after wake-up) + * @dev: PCI device to have its BARs restored + * + * Restore the BAR values for a given device, so as to make it + * accessible by its driver. + */ +void +pci_restore_bars(struct pci_dev *dev) +{ + int i, numres; + + switch (dev->hdr_type) { + case PCI_HEADER_TYPE_NORMAL: + numres = 6; + break; + case PCI_HEADER_TYPE_BRIDGE: + numres = 2; + break; + case PCI_HEADER_TYPE_CARDBUS: + numres = 1; + break; + default: + /* Should never get here, but just in case... */ + return; + } + + for (i = 0; i < numres; i ++) + pci_update_resource(dev, &dev->resource[i], i); +} + /** * pci_set_power_state - Set the power state of a PCI device * @dev: PCI device to be suspended @@ -239,7 +270,7 @@ int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t); int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { - int pm; + int pm, need_restore = 0; u16 pmcsr, pmc; /* bound the state we're entering */ @@ -278,14 +309,17 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) return -EIO; } + pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); + /* If we're in D3, force entire word to 0. * This doesn't affect PME_Status, disables PME_En, and * sets PowerState to 0. */ - if (dev->current_state >= PCI_D3hot) + if (dev->current_state >= PCI_D3hot) { + if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) + need_restore = 1; pmcsr = 0; - else { - pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); + } else { pmcsr &= ~PCI_PM_CTRL_STATE_MASK; pmcsr |= state; } @@ -308,6 +342,22 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) platform_pci_set_power_state(dev, state); dev->current_state = state; + + /* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT + * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning + * from D3hot to D0 _may_ perform an internal reset, thereby + * going to "D0 Uninitialized" rather than "D0 Initialized". + * For example, at least some versions of the 3c905B and the + * 3c556B exhibit this behaviour. + * + * At least some laptop BIOSen (e.g. the Thinkpad T21) leave + * devices in a D3hot state at boot. Consequently, we need to + * restore at least the BARs so that the device will be + * accessible to its driver. + */ + if (need_restore) + pci_restore_bars(dev); + return 0; } @@ -805,6 +855,7 @@ struct pci_dev *isa_bridge; EXPORT_SYMBOL(isa_bridge); #endif +EXPORT_SYMBOL_GPL(pci_restore_bars); EXPORT_SYMBOL(pci_enable_device_bars); EXPORT_SYMBOL(pci_enable_device); EXPORT_SYMBOL(pci_disable_device); diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 1ca21d2ba11c..878fd0a65c02 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -26,7 +26,7 @@ #include "pci.h" -static void +void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) { struct pci_bus_region region; diff --git a/include/linux/pci.h b/include/linux/pci.h index 8621cf42b46f..98bdd95fcee9 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -225,6 +225,7 @@ #define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */ #define PCI_PM_CTRL 4 /* PM control and status register */ #define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ +#define PCI_PM_CTRL_NO_SOFT_RESET 0x0004 /* No reset for D3hot->D0 */ #define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */ #define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ #define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ @@ -816,7 +817,9 @@ int pci_set_mwi(struct pci_dev *dev); void pci_clear_mwi(struct pci_dev *dev); int pci_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); +void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); int pci_assign_resource(struct pci_dev *dev, int i); +void pci_restore_bars(struct pci_dev *dev); /* ROM control related routines */ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size); -- cgit v1.2.3 From 43c34735524d5b1c9b9e5d63b49dd4c1b394bde4 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 4 Aug 2005 18:06:21 -0700 Subject: [PATCH] pci and yenta: pcibios_bus_to_resource In yenta_socket, we default to using the resource setting of the CardBus bridge. However, this is a PCI-bus-centric view of resources and thus needs to be converted to generic resources first. Therefore, add a call to pcibios_bus_to_resource() call in between. This function is a mere wrapper on x86 and friends, however on some others it already exists, is added in this patch (alpha, arm, ppc, ppc64) or still needs to be provided (parisc -- where is its pcibios_resource_to_bus() ?). Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- arch/alpha/kernel/pci.c | 16 ++++++++++++++++ arch/arm/kernel/bios32.c | 17 +++++++++++++++++ arch/ppc/kernel/pci.c | 15 +++++++++++++++ arch/ppc64/kernel/pci.c | 20 ++++++++++++++++++++ drivers/pcmcia/yenta_socket.c | 15 ++++++--------- include/asm-alpha/pci.h | 3 +++ include/asm-arm/pci.h | 4 ++++ include/asm-generic/pci.h | 8 ++++++++ include/asm-parisc/pci.h | 4 ++++ include/asm-ppc/pci.h | 4 ++++ include/asm-ppc64/pci.h | 4 ++++ 11 files changed, 101 insertions(+), 9 deletions(-) diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 1f36bbd0ed5d..2a8b364c822e 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -350,8 +350,24 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, region->end = res->end - offset; } +void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + struct pci_controller *hose = (struct pci_controller *)dev->sysdata; + unsigned long offset = 0; + + if (res->flags & IORESOURCE_IO) + offset = hose->io_space->start; + else if (res->flags & IORESOURCE_MEM) + offset = hose->mem_space->start; + + res->start = region->start + offset; + res->end = region->end + offset; +} + #ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pcibios_resource_to_bus); +EXPORT_SYMBOL(pcibios_bus_to_resource); #endif int diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index ad26e98f1e62..c4923fac8dff 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -447,9 +447,26 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, region->end = res->end - offset; } +void __devinit +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + struct pci_sys_data *root = dev->sysdata; + unsigned long offset = 0; + + if (res->flags & IORESOURCE_IO) + offset = root->io_offset; + if (res->flags & IORESOURCE_MEM) + offset = root->mem_offset; + + res->start = region->start + offset; + res->end = region->end + offset; +} + #ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pcibios_fixup_bus); EXPORT_SYMBOL(pcibios_resource_to_bus); +EXPORT_SYMBOL(pcibios_bus_to_resource); #endif /* diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 70cfb6ffd877..7b3586a3bf30 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -160,6 +160,21 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, } EXPORT_SYMBOL(pcibios_resource_to_bus); +void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + unsigned long offset = 0; + struct pci_controller *hose = dev->sysdata; + + if (hose && res->flags & IORESOURCE_IO) + offset = (unsigned long)hose->io_base_virt - isa_io_base; + else if (hose && res->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; + res->start = region->start + offset; + res->end = region->end + offset; +} +EXPORT_SYMBOL(pcibios_bus_to_resource); + /* * We need to avoid collisions with `mirrored' VGA ports * and other strange ISA hardware, so we always want the diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index ae6f579d3fa0..d0d55c7908ef 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -108,8 +108,28 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region region->end = res->end - offset; } +void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + unsigned long offset = 0; + struct pci_controller *hose = pci_bus_to_host(dev->bus); + + if (!hose) + return; + + if (res->flags & IORESOURCE_IO) + offset = (unsigned long)hose->io_base_virt - pci_io_base; + + if (res->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; + + res->start = region->start + offset; + res->end = region->end + offset; +} + #ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pcibios_resource_to_bus); +EXPORT_SYMBOL(pcibios_bus_to_resource); #endif /* diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 91e7457d5b04..62fd705203fb 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -605,9 +605,8 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res, static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) { - struct pci_bus *bus; struct resource *root, *res; - u32 start, end; + struct pci_bus_region region; unsigned mask; res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; @@ -620,15 +619,13 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ if (type & IORESOURCE_IO) mask = ~3; - bus = socket->dev->subordinate; - res->name = bus->name; + res->name = socket->dev->subordinate->name; res->flags = type; - start = config_readl(socket, addr_start) & mask; - end = config_readl(socket, addr_end) | ~mask; - if (start && end > start && !override_bios) { - res->start = start; - res->end = end; + region.start = config_readl(socket, addr_start) & mask; + region.end = config_readl(socket, addr_end) | ~mask; + if (region.start && region.end > region.start && !override_bios) { + pcibios_bus_to_resource(socket->dev, res, ®ion); root = pci_find_parent_resource(socket->dev, res); if (root && (request_resource(root, res) == 0)) return; diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h index 28957697e59c..f681e675b823 100644 --- a/include/asm-alpha/pci.h +++ b/include/asm-alpha/pci.h @@ -251,6 +251,9 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) extern void pcibios_resource_to_bus(struct pci_dev *, struct pci_bus_region *, struct resource *); +extern void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region); + #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index static inline int pci_proc_domain(struct pci_bus *bus) diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h index b28f1c95dd62..38ea5899a580 100644 --- a/include/asm-arm/pci.h +++ b/include/asm-arm/pci.h @@ -60,6 +60,10 @@ extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res); +extern void +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region); + static inline void pcibios_add_platform_entries(struct pci_dev *dev) { } diff --git a/include/asm-generic/pci.h b/include/asm-generic/pci.h index 9d4cc47bde39..ee1d8b5d8168 100644 --- a/include/asm-generic/pci.h +++ b/include/asm-generic/pci.h @@ -22,6 +22,14 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, region->end = res->end; } +static inline void +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + res->start = region->start; + res->end = region->end; +} + #define pcibios_scan_all_fns(a, b) 0 #ifndef HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h index ee741c150176..98d79a3d54fa 100644 --- a/include/asm-parisc/pci.h +++ b/include/asm-parisc/pci.h @@ -253,6 +253,10 @@ extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res); +extern void +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region); + static inline void pcibios_add_platform_entries(struct pci_dev *dev) { } diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h index a13d55870e62..a811e440c978 100644 --- a/include/asm-ppc/pci.h +++ b/include/asm-ppc/pci.h @@ -105,6 +105,10 @@ extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res); +extern void +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region); + extern void pcibios_add_platform_entries(struct pci_dev *dev); struct file; diff --git a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h index faa772223075..4d057452f59b 100644 --- a/include/asm-ppc64/pci.h +++ b/include/asm-ppc64/pci.h @@ -134,6 +134,10 @@ extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res); +extern void +pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region); + extern int unmap_bus_range(struct pci_bus *bus); -- cgit v1.2.3 From 003ba5153582427b1df2347553529299872961e5 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 4 Aug 2005 18:06:36 -0700 Subject: [PATCH] USB: ub documentation update The patch which went in was correct, but not quite what I had in mind. Here is a patch to update that a little bit. Original patch is at: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=4749f32da939d4e4160541b2cadc22492bb507ec Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- Documentation/usb/usbmon.txt | 2 +- drivers/usb/mon/Kconfig | 9 ++++----- drivers/usb/mon/Makefile | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt index f1896ee3bb2a..63cb7edd177e 100644 --- a/Documentation/usb/usbmon.txt +++ b/Documentation/usb/usbmon.txt @@ -102,7 +102,7 @@ Here is the list of words, from left to right: - URB Status. This field makes no sense for submissions, but is present to help scripts with parsing. In error case, it contains the error code. In case of a setup packet, it contains a Setup Tag. If scripts read a number - in this field, the proceed to read Data Length. Otherwise, they read + in this field, they proceed to read Data Length. Otherwise, they read the setup packet before reading the Data Length. - Setup packet, if present, consists of 5 words: one of each for bmRequestType, bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0. diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig index 777642e26b9a..deb9ddffa402 100644 --- a/drivers/usb/mon/Kconfig +++ b/drivers/usb/mon/Kconfig @@ -9,9 +9,8 @@ config USB_MON help If you say Y here, a component which captures the USB traffic between peripheral-specific drivers and HC drivers will be built. - The USB_MON is similar in spirit and may be compatible with Dave - Harding's USBMon. + For more information, see . - This is somewhat experimental at this time, but it should be safe, - as long as you aren't using modular USB and try to remove this - module. + This is somewhat experimental at this time, but it should be safe. + + If unsure, say Y. diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile index f18d10ce91f9..b0015b8a1d1f 100644 --- a/drivers/usb/mon/Makefile +++ b/drivers/usb/mon/Makefile @@ -4,4 +4,5 @@ usbmon-objs := mon_main.o mon_stat.o mon_text.o +# This does not use CONFIG_USB_MON because we want this to use a tristate. obj-$(CONFIG_USB) += usbmon.o -- cgit v1.2.3 From 7dedacf4270a810fadcca887ac85d267b5f1882d Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 4 Aug 2005 18:06:41 -0700 Subject: [PATCH] USB: ehci: microframe handling fix This patch has a one line oops fix, plus related cleanups. - The bugfix uses microframe scheduling data given to the hardware to test "is this a periodic QH", rather than testing for nonzero period. (Prevents an oops by providing the correct answer.) - The cleanup going along with the patch should make it clearer what's going on whenever those bitfields are accessed. The bug came about when, around January, two new kinds of EHCI interrupt scheduling operation were added, involving both the high speed (24 KBytes per millisec) and low/full speed (1-64 bytes per millisec) microframe scheduling. A driver for the Edirol UA-1000 Audio Capture Unit ran into the oops; it used one of the newly supported high speed modes. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/host/ehci-dbg.c | 2 +- drivers/usb/host/ehci-q.c | 5 +++-- drivers/usb/host/ehci-sched.c | 13 +++++++------ drivers/usb/host/ehci.h | 5 +++++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 50cb01831075..b01efb6b36f6 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -527,7 +527,7 @@ show_periodic (struct class_device *class_dev, char *buf) p.qh->period, le32_to_cpup (&p.qh->hw_info2) /* uframe masks */ - & 0xffff, + & (QH_CMASK | QH_SMASK), p.qh); size -= temp; next += temp; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 4f97a4ad1ed3..20df01a79b2e 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -222,7 +222,7 @@ __acquires(ehci->lock) struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; /* S-mask in a QH means it's an interrupt urb */ - if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) { + if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) { /* ... update hc-wide periodic stats (for usbfs) */ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; @@ -428,7 +428,8 @@ halt: /* should be rare for periodic transfers, * except maybe high bandwidth ... */ - if (qh->period) { + if ((__constant_cpu_to_le32 (QH_SMASK) + & qh->hw_info2) != 0) { intr_deschedule (ehci, qh); (void) qh_schedule (ehci, qh); } else diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 9af4f64532a9..b56f25864ed6 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -301,7 +301,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) dev_dbg (&qh->dev->dev, "link qh%d-%04x/%p start %d [%d/%d us]\n", - period, le32_to_cpup (&qh->hw_info2) & 0xffff, + period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); /* high bandwidth, or otherwise every microframe */ @@ -385,7 +385,8 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) dev_dbg (&qh->dev->dev, "unlink qh%d-%04x/%p start %d [%d/%d us]\n", - qh->period, le32_to_cpup (&qh->hw_info2) & 0xffff, + qh->period, + le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); /* qh->qh_next still "live" to HC */ @@ -411,7 +412,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) * active high speed queues may need bigger delays... */ if (list_empty (&qh->qtd_list) - || (__constant_cpu_to_le32 (0x0ff << 8) + || (__constant_cpu_to_le32 (QH_CMASK) & qh->hw_info2) != 0) wait = 2; else @@ -533,7 +534,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) /* reuse the previous schedule slots, if we can */ if (frame < qh->period) { - uframe = ffs (le32_to_cpup (&qh->hw_info2) & 0x00ff); + uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK); status = check_intr_schedule (ehci, frame, --uframe, qh, &c_mask); } else { @@ -569,10 +570,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->start = frame; /* reset S-frame and (maybe) C-frame masks */ - qh->hw_info2 &= __constant_cpu_to_le32 (~0xffff); + qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK)); qh->hw_info2 |= qh->period ? cpu_to_le32 (1 << uframe) - : __constant_cpu_to_le32 (0xff); + : __constant_cpu_to_le32 (QH_SMASK); qh->hw_info2 |= c_mask; } else ehci_dbg (ehci, "reused qh %p schedule\n", qh); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 4df498231752..a7542157534c 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -385,6 +385,11 @@ struct ehci_qh { __le32 hw_info1; /* see EHCI 3.6.2 */ #define QH_HEAD 0x00008000 __le32 hw_info2; /* see EHCI 3.6.2 */ +#define QH_SMASK 0x000000ff +#define QH_CMASK 0x0000ff00 +#define QH_HUBADDR 0x007f0000 +#define QH_HUBPORT 0x3f800000 +#define QH_MULT 0xc0000000 __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ /* qtd overlay (hardware parts of a struct ehci_qtd) */ -- cgit v1.2.3 From f10eff26831159f52353e8f15c37cdb2935d5fbf Mon Sep 17 00:00:00 2001 From: Olav Kongas Date: Thu, 4 Aug 2005 18:06:47 -0700 Subject: [PATCH] USB: Fix setup packet initialization in isp116x-hcd When recently addressing remarks by Alexey Dobriyan about the isp116x-hcd, I introduced a bug in the driver. Please apply the attached patch to fix it. Signed-off-by: Olav Kongas Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/host/isp116x-hcd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 50b1970fe6b6..76cb496c5836 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -229,9 +229,11 @@ static void preproc_atl_queue(struct isp116x *isp116x) struct isp116x_ep *ep; struct urb *urb; struct ptd *ptd; - u16 toggle = 0, dir = PTD_DIR_SETUP, len; + u16 len; for (ep = isp116x->atl_active; ep; ep = ep->active) { + u16 toggle = 0, dir = PTD_DIR_SETUP; + BUG_ON(list_empty(&ep->hep->urb_list)); urb = container_of(ep->hep->urb_list.next, struct urb, urb_list); -- cgit v1.2.3 From 0c3dba1534569734ba353afdf3f11def497ff2ac Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Thu, 4 Aug 2005 21:12:54 -0400 Subject: [PATCH] Clean up inotify delete race fix This avoids the whole #ifdef mess by just getting a copy of dentry->d_inode before d_delete is called - that makes the codepaths the same for the INOTIFY/DNOTIFY cases as for the regular no-notify case. I've been running this under a Gnome session for the last 10 minutes. Inotify is being used extensively. Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/namei.c | 9 ++------- include/linux/fsnotify.h | 4 +--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 83559dce4286..32accb6a672f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1874,14 +1874,9 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) /* We don't d_delete() NFS sillyrenamed files--they still exist. */ if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { -#if defined(CONFIG_INOTIFY) || defined(CONFIG_DNOTIFY) - dget(dentry); + struct inode *inode = dentry->d_inode; d_delete(dentry); - fsnotify_unlink(dentry, dir); - dput(dentry); -#else - d_delete(dentry); -#endif + fsnotify_unlink(dentry, inode, dir); } return error; diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index e96a4306ab3b..1cb4935348d8 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -46,10 +46,8 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, /* * fsnotify_unlink - file was unlinked */ -static inline void fsnotify_unlink(struct dentry *dentry, struct inode *dir) +static inline void fsnotify_unlink(struct dentry *dentry, struct inode *inode, struct inode *dir) { - struct inode *inode = dentry->d_inode; - inode_dir_notify(dir, DN_DELETE); inotify_inode_queue_event(dir, IN_DELETE, 0, dentry->d_name.name); inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL); -- cgit v1.2.3 From 846998ae87a80b0fd45b4cf5cf001a159d746f27 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 4 Aug 2005 19:52:01 -0700 Subject: [PATCH] tcp: fix TSO sizing bugs MSS changes can be lost since we preemptively initialize the tso_segs count for an SKB before we %100 commit to sending it out. So, by the time we send it out, the tso_size information can be stale due to PMTU events. This mucks up all of the logic in our send engine, and can even result in the BUG() triggering in tcp_tso_should_defer(). Another problem we have is that we're storing the tp->mss_cache, not the SACK block normalized MSS, as the tso_size. That's wrong too. Signed-off-by: David S. Miller Cc: Herbert Xu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- net/ipv4/tcp_output.c | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e3f8ea1bfa9c..e118b4b5b326 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -403,11 +403,9 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) sk->sk_send_head = skb; } -static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb) +static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now) { - struct tcp_sock *tp = tcp_sk(sk); - - if (skb->len <= tp->mss_cache || + if (skb->len <= mss_now || !(sk->sk_route_caps & NETIF_F_TSO)) { /* Avoid the costly divide in the normal * non-TSO case. @@ -417,10 +415,10 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb) } else { unsigned int factor; - factor = skb->len + (tp->mss_cache - 1); - factor /= tp->mss_cache; + factor = skb->len + (mss_now - 1); + factor /= mss_now; skb_shinfo(skb)->tso_segs = factor; - skb_shinfo(skb)->tso_size = tp->mss_cache; + skb_shinfo(skb)->tso_size = mss_now; } } @@ -429,7 +427,7 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb) * packet to the list. This won't be called frequently, I hope. * Remember, these are still headerless SKBs at this point. */ -static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len) +static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss_now) { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *buff; @@ -492,8 +490,8 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len) } /* Fix up tso_factor for both original and new SKB. */ - tcp_set_skb_tso_segs(sk, skb); - tcp_set_skb_tso_segs(sk, buff); + tcp_set_skb_tso_segs(sk, skb, mss_now); + tcp_set_skb_tso_segs(sk, buff, mss_now); if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { tp->lost_out += tcp_skb_pcount(skb); @@ -569,7 +567,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) * factor and mss. */ if (tcp_skb_pcount(skb) > 1) - tcp_set_skb_tso_segs(sk, skb); + tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk, 1)); return 0; } @@ -734,12 +732,14 @@ static inline unsigned int tcp_cwnd_test(struct tcp_sock *tp, struct sk_buff *sk /* This must be invoked the first time we consider transmitting * SKB onto the wire. */ -static inline int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb) +static inline int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now) { int tso_segs = tcp_skb_pcount(skb); - if (!tso_segs) { - tcp_set_skb_tso_segs(sk, skb); + if (!tso_segs || + (tso_segs > 1 && + skb_shinfo(skb)->tso_size != mss_now)) { + tcp_set_skb_tso_segs(sk, skb, mss_now); tso_segs = tcp_skb_pcount(skb); } return tso_segs; @@ -817,7 +817,7 @@ static unsigned int tcp_snd_test(struct sock *sk, struct sk_buff *skb, struct tcp_sock *tp = tcp_sk(sk); unsigned int cwnd_quota; - tcp_init_tso_segs(sk, skb); + tcp_init_tso_segs(sk, skb, cur_mss); if (!tcp_nagle_test(tp, skb, cur_mss, nonagle)) return 0; @@ -854,7 +854,7 @@ int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp) * know that all the data is in scatter-gather pages, and that the * packet has never been sent out before (and thus is not cloned). */ -static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len) +static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, unsigned int mss_now) { struct sk_buff *buff; int nlen = skb->len - len; @@ -887,8 +887,8 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len) skb_split(skb, buff, len); /* Fix up tso_factor for both original and new SKB. */ - tcp_set_skb_tso_segs(sk, skb); - tcp_set_skb_tso_segs(sk, buff); + tcp_set_skb_tso_segs(sk, skb, mss_now); + tcp_set_skb_tso_segs(sk, buff, mss_now); /* Link BUFF into the send queue. */ skb_header_release(buff); @@ -976,7 +976,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) if (unlikely(!skb)) return 0; - tso_segs = tcp_init_tso_segs(sk, skb); + tso_segs = tcp_init_tso_segs(sk, skb, mss_now); cwnd_quota = tcp_cwnd_test(tp, skb); if (unlikely(!cwnd_quota)) goto out; @@ -1006,11 +1006,11 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) limit = skb->len - trim; } if (skb->len > limit) { - if (tso_fragment(sk, skb, limit)) + if (tso_fragment(sk, skb, limit, mss_now)) break; } } else if (unlikely(skb->len > mss_now)) { - if (unlikely(tcp_fragment(sk, skb, mss_now))) + if (unlikely(tcp_fragment(sk, skb, mss_now, mss_now))) break; } @@ -1039,7 +1039,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) skb = sk->sk_send_head; if (!skb) break; - tso_segs = tcp_init_tso_segs(sk, skb); + tso_segs = tcp_init_tso_segs(sk, skb, mss_now); } if (likely(sent_pkts)) { @@ -1076,7 +1076,7 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now) BUG_ON(!skb || skb->len < mss_now); - tso_segs = tcp_init_tso_segs(sk, skb); + tso_segs = tcp_init_tso_segs(sk, skb, mss_now); cwnd_quota = tcp_snd_test(sk, skb, mss_now, TCP_NAGLE_PUSH); if (likely(cwnd_quota)) { @@ -1093,11 +1093,11 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now) limit = skb->len - trim; } if (skb->len > limit) { - if (unlikely(tso_fragment(sk, skb, limit))) + if (unlikely(tso_fragment(sk, skb, limit, mss_now))) return; } } else if (unlikely(skb->len > mss_now)) { - if (unlikely(tcp_fragment(sk, skb, mss_now))) + if (unlikely(tcp_fragment(sk, skb, mss_now, mss_now))) return; } @@ -1388,7 +1388,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) int old_factor = tcp_skb_pcount(skb); int new_factor; - if (tcp_fragment(sk, skb, cur_mss)) + if (tcp_fragment(sk, skb, cur_mss, cur_mss)) return -ENOMEM; /* We'll try again later. */ /* New SKB created, account for it. */ @@ -1991,7 +1991,7 @@ int tcp_write_wakeup(struct sock *sk) skb->len > mss) { seg_size = min(seg_size, mss); TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; - if (tcp_fragment(sk, skb, seg_size)) + if (tcp_fragment(sk, skb, seg_size, mss)) return -1; /* SWS override triggered forced fragmentation. * Disable TSO, the connection is too sick. */ @@ -2000,7 +2000,7 @@ int tcp_write_wakeup(struct sock *sk) sk->sk_route_caps &= ~NETIF_F_TSO; } } else if (!tcp_skb_pcount(skb)) - tcp_set_skb_tso_segs(sk, skb); + tcp_set_skb_tso_segs(sk, skb, mss); TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; TCP_SKB_CB(skb)->when = tcp_time_stamp; -- cgit v1.2.3 From b68e9f857271189bd7a59b74c99890de9195b0e1 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 4 Aug 2005 19:52:02 -0700 Subject: [PATCH] tcp: fix TSO cwnd caching bug tcp_write_xmit caches the cwnd value indirectly in cwnd_quota. When tcp_transmit_skb reduces the cwnd because of tcp_enter_cwr, the cached value becomes invalid. This patch ensures that the cwnd value is always reread after each tcp_transmit_skb call. Signed-off-by: Herbert Xu Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- net/ipv4/tcp_output.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e118b4b5b326..7d076f0db100 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -972,19 +972,18 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) if (unlikely(sk->sk_state == TCP_CLOSE)) return 0; - skb = sk->sk_send_head; - if (unlikely(!skb)) - return 0; - - tso_segs = tcp_init_tso_segs(sk, skb, mss_now); - cwnd_quota = tcp_cwnd_test(tp, skb); - if (unlikely(!cwnd_quota)) - goto out; - sent_pkts = 0; - while (likely(tcp_snd_wnd_test(tp, skb, mss_now))) { + while ((skb = sk->sk_send_head)) { + tso_segs = tcp_init_tso_segs(sk, skb, mss_now); BUG_ON(!tso_segs); + cwnd_quota = tcp_cwnd_test(tp, skb); + if (!cwnd_quota) + break; + + if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now))) + break; + if (tso_segs == 1) { if (unlikely(!tcp_nagle_test(tp, skb, mss_now, (tcp_skb_is_last(sk, skb) ? @@ -1026,27 +1025,12 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) tcp_minshall_update(tp, mss_now, skb); sent_pkts++; - - /* Do not optimize this to use tso_segs. If we chopped up - * the packet above, tso_segs will no longer be valid. - */ - cwnd_quota -= tcp_skb_pcount(skb); - - BUG_ON(cwnd_quota < 0); - if (!cwnd_quota) - break; - - skb = sk->sk_send_head; - if (!skb) - break; - tso_segs = tcp_init_tso_segs(sk, skb, mss_now); } if (likely(sent_pkts)) { tcp_cwnd_validate(sk, tp); return 0; } -out: return !tp->packets_out && sk->sk_send_head; } -- cgit v1.2.3 From 2f60f8d3573ff90fe5d75a6d11fd2add1248e7d6 Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Thu, 4 Aug 2005 19:52:03 -0700 Subject: [PATCH] __vm_enough_memory() signedness fix We have found what seems to be a small bug in __vm_enough_memory() when sysctl_overcommit_memory is set to OVERCOMMIT_NEVER. When this bug occurs the systems fails to boot, with /sbin/init whining about fork() returning ENOMEM. We hunted down the problem to this: The deferred update mecanism used in vm_acct_memory(), on a SMP system, allows the vm_committed_space counter to have a negative value. This should not be a problem since this counter is known to be inaccurate. But in __vm_enough_memory() this counter is compared to the `allowed' variable, which is an unsigned long. This comparison is broken since it will consider the negative values of vm_committed_space to be huge positive values, resulting in a memory allocation failure. Signed-off-by: Signed-off-by: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mmap.c | 6 +++++- mm/nommu.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index da3fa90a0aae..404319477e71 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -143,7 +143,11 @@ int __vm_enough_memory(long pages, int cap_sys_admin) leave 3% of the size of this process for other processes */ allowed -= current->mm->total_vm / 32; - if (atomic_read(&vm_committed_space) < allowed) + /* + * cast `allowed' as a signed long because vm_committed_space + * sometimes has a negative value + */ + if (atomic_read(&vm_committed_space) < (long)allowed) return 0; vm_unacct_memory(pages); diff --git a/mm/nommu.c b/mm/nommu.c index ce74452c02d9..fd4e8df0f02d 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1167,7 +1167,11 @@ int __vm_enough_memory(long pages, int cap_sys_admin) leave 3% of the size of this process for other processes */ allowed -= current->mm->total_vm / 32; - if (atomic_read(&vm_committed_space) < allowed) + /* + * cast `allowed' as a signed long because vm_committed_space + * sometimes has a negative value + */ + if (atomic_read(&vm_committed_space) < (long)allowed) return 0; vm_unacct_memory(pages); -- cgit v1.2.3 From b7656e7f2944984befa3ab99a5b99f99a23b302b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 5 Aug 2005 04:12:48 -0700 Subject: [IPV4]: Fix memory leak during fib_info hash expansion. When we grow the tables, we forget to free the olds ones up. Noticed by Yan Zheng. Signed-off-by: David S. Miller --- net/ipv4/fib_semantics.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index c886b28ba9f5..e278cb9d0075 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -593,10 +593,13 @@ static void fib_hash_move(struct hlist_head *new_info_hash, struct hlist_head *new_laddrhash, unsigned int new_size) { + struct hlist_head *old_info_hash, *old_laddrhash; unsigned int old_size = fib_hash_size; - unsigned int i; + unsigned int i, bytes; write_lock(&fib_info_lock); + old_info_hash = fib_info_hash; + old_laddrhash = fib_info_laddrhash; fib_hash_size = new_size; for (i = 0; i < old_size; i++) { @@ -636,6 +639,10 @@ static void fib_hash_move(struct hlist_head *new_info_hash, fib_info_laddrhash = new_laddrhash; write_unlock(&fib_info_lock); + + bytes = old_size * sizeof(struct hlist_head *); + fib_hash_free(old_info_hash, bytes); + fib_hash_free(old_laddrhash, bytes); } struct fib_info * -- cgit v1.2.3 From 403fe5ae57c831968c3dbbaba291ae825a1c5aaa Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Fri, 5 Aug 2005 15:50:07 +0200 Subject: [PATCH] rtc: msleep() cannot be used from interrupt Since the beginning of July my Opteron box was randomly crashing and being rebooted by hardware watchdog. Today it finally did it in front of me, and this patch will hopefully fix it. The problem is that at the end of June (the 28th, to be exact: commit 47f176fdaf8924bc83fddcf9658f2fd3ef60d573, "[PATCH] Using msleep() instead of HZ") rtc_get_rtc_time was converted to use msleep() instead of busy waiting. But rtc_get_rtc_time is used by hpet_rtc_interrupt, and scheduling is not allowed during interrupt. So I'm reverting this part of original change, replacing msleep() back with busy loop. The original code was busy waiting for up to 20ms, but on my hardware in the worst case update-in-progress bit was asserted for at most 363 passes through loop (on 2GHz dual Opteron), much less than even one jiffie, not even talking about 20ms. So I changed code to just wait only as long as necessary. Otherwise when RTC was set to generate 8192Hz timer, it stopped doing anything for 20ms (160 pulses were skipped!) from time to time, and this is rather suboptimal as far as I can tell. Signed-off-by: Petr Vandrovec Signed-off-by: Linus Torvalds --- drivers/char/rtc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index d8f9e94ae475..cd4fe8b1709f 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -1209,6 +1209,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file) void rtc_get_rtc_time(struct rtc_time *rtc_tm) { + unsigned long uip_watchdog = jiffies; unsigned char ctrl; #ifdef CONFIG_MACH_DECSTATION unsigned int real_year; @@ -1224,8 +1225,10 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm) * Once the read clears, read the RTC time (again via ioctl). Easy. */ - if (rtc_is_updating() != 0) - msleep(20); + while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) { + barrier(); + cpu_relax(); + } /* * Only the values that we read from the RTC are set. We leave -- cgit v1.2.3 From 30e835e36648b15fb80797ace0a0e2afcf97618d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 5 Aug 2005 11:59:32 -0700 Subject: [PATCH] REPORTING-BUGS: track regressions Add a new record to the REPORTING-BUGS template: "Most recent kernel version which did not have the bug:". So we can spot regressions more easily. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- REPORTING-BUGS | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/REPORTING-BUGS b/REPORTING-BUGS index 2045eaea2d9e..224c34741d32 100644 --- a/REPORTING-BUGS +++ b/REPORTING-BUGS @@ -41,18 +41,19 @@ summary from [1.]>" for easy identification by the developers [2.] Full description of the problem/report: [3.] Keywords (i.e., modules, networking, kernel): [4.] Kernel version (from /proc/version): -[5.] Output of Oops.. message (if applicable) with symbolic information +[5.] Most recent kernel version which did not have the bug: +[6.] Output of Oops.. message (if applicable) with symbolic information resolved (see Documentation/oops-tracing.txt) -[6.] A small shell script or example program which triggers the +[7.] A small shell script or example program which triggers the problem (if possible) -[7.] Environment -[7.1.] Software (add the output of the ver_linux script here) -[7.2.] Processor information (from /proc/cpuinfo): -[7.3.] Module information (from /proc/modules): -[7.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem) -[7.5.] PCI information ('lspci -vvv' as root) -[7.6.] SCSI information (from /proc/scsi/scsi) -[7.7.] Other information that might be relevant to the problem +[8.] Environment +[8.1.] Software (add the output of the ver_linux script here) +[8.2.] Processor information (from /proc/cpuinfo): +[8.3.] Module information (from /proc/modules): +[8.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem) +[8.5.] PCI information ('lspci -vvv' as root) +[8.6.] SCSI information (from /proc/scsi/scsi) +[8.7.] Other information that might be relevant to the problem (please look in /proc and include all information that you think to be relevant): [X.] Other notes, patches, fixes, workarounds: -- cgit v1.2.3 From f9abb020405c94edb0717315f1510086b1574a22 Mon Sep 17 00:00:00 2001 From: Marcel Selhorst Date: Fri, 5 Aug 2005 11:59:33 -0700 Subject: [PATCH] tpm_infineon: Support for new TPM 1.2 and PNPACPI This patch includes support for the new Infineon Trusted Platform Module SLB 9635 TT 1.2 and does further include ACPI-support for both chip versions (SLD 9630 TT 1.1 and SLB9635 TT 1.2). Since the ioports and configuration registers are not correctly set on some machines, the configuration is now done via PNPACPI, which reads out the correct values out of the DSDT-table. Note that you have to have CONFIG_PNP, CONFIG_ACPI_BUS and CONFIG_PNPACPI enabled to run this driver (assuming that mainboards including a TPM do have the need for ACPI anyway). Signed-off-by: Marcel Selhorst Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tpm/Kconfig | 11 +-- drivers/char/tpm/tpm_infineon.c | 146 +++++++++++++++++++++++++++++----------- 2 files changed, 113 insertions(+), 44 deletions(-) diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 94a3b3e20bf9..79e9832ef1f3 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -17,6 +17,8 @@ config TCG_TPM obtained at: . To compile this driver as a module, choose M here; the module will be called tpm. If unsure, say N. + Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI_BUS + and CONFIG_PNPACPI. config TCG_NSC tristate "National Semiconductor TPM Interface" @@ -36,12 +38,13 @@ config TCG_ATMEL as a module, choose M here; the module will be called tpm_atmel. config TCG_INFINEON - tristate "Infineon Technologies SLD 9630 TPM Interface" - depends on TCG_TPM + tristate "Infineon Technologies TPM Interface" + depends on TCG_TPM && PNPACPI ---help--- If you have a TPM security chip from Infineon Technologies - say Yes and it will be accessible from within Linux. To - compile this driver as a module, choose M here; the module + (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it + will be accessible from within Linux. + To compile this driver as a module, choose M here; the module will be called tpm_infineon. Further information on this driver and the supported hardware can be found at http://www.prosec.rub.de/tpm diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 0e3241645c19..dc8c540391fd 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -1,7 +1,7 @@ /* * Description: * Device Driver for the Infineon Technologies - * SLD 9630 TT Trusted Platform Module + * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module * Specifications at www.trustedcomputinggroup.org * * Copyright (C) 2005, Marcel Selhorst @@ -12,9 +12,10 @@ * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2 of the * License. - * */ +#include +#include #include "tpm.h" /* Infineon specific definitions */ @@ -26,8 +27,11 @@ #define TPM_MSLEEP_TIME 3 /* gives number of max. msleep()-calls before throwing timeout */ #define TPM_MAX_TRIES 5000 -#define TCPA_INFINEON_DEV_VEN_VALUE 0x15D1 -#define TPM_DATA (TPM_ADDR + 1) & 0xff +#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1 + +/* These values will be filled after ACPI-call */ +static int TPM_INF_DATA = 0; +static int TPM_INF_ADDR = 0; /* TPM header definitions */ enum infineon_tpm_header { @@ -305,9 +309,10 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) static void tpm_inf_cancel(struct tpm_chip *chip) { - /* Nothing yet! - This has something to do with the internal functions - of the TPM. Abort isn't really necessary... + /* + Since we are using the legacy mode to communicate + with the TPM, we have no cancel functions, but have + a workaround for interrupting the TPM through WTX. */ } @@ -345,6 +350,32 @@ static struct tpm_vendor_specific tpm_inf = { .miscdev = {.fops = &inf_ops,}, }; +static const struct pnp_device_id tpm_pnp_tbl[] = { + /* Infineon TPMs */ + {"IFX0101", 0}, + {"IFX0102", 0}, + {"", 0} +}; + +static int __devinit tpm_inf_acpi_probe(struct pnp_dev *dev, + const struct pnp_device_id *dev_id) +{ + TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff); + TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff); + tpm_inf.base = pnp_port_start(dev, 1); + dev_info(&dev->dev, "Found %s with ID %s\n", + dev->name, dev_id->id); + if (!((tpm_inf.base >> 8) & 0xff)) + tpm_inf.base = 0; + return 0; +} + +static struct pnp_driver tpm_inf_pnp = { + .name = "tpm_inf_pnp", + .id_table = tpm_pnp_tbl, + .probe = tpm_inf_acpi_probe, +}; + static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { @@ -353,64 +384,99 @@ static int __devinit tpm_inf_probe(struct pci_dev *pci_dev, int vendorid[2]; int version[2]; int productid[2]; + char chipname[20]; if (pci_enable_device(pci_dev)) return -EIO; dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device); + /* read IO-ports from ACPI */ + pnp_register_driver(&tpm_inf_pnp); + pnp_unregister_driver(&tpm_inf_pnp); + + /* Make sure, we have received valid config ports */ + if (!TPM_INF_ADDR) { + pci_disable_device(pci_dev); + return -EIO; + } + /* query chip for its vendor, its version number a.s.o. */ - outb(ENABLE_REGISTER_PAIR, TPM_ADDR); - outb(IDVENL, TPM_ADDR); - vendorid[1] = inb(TPM_DATA); - outb(IDVENH, TPM_ADDR); - vendorid[0] = inb(TPM_DATA); - outb(IDPDL, TPM_ADDR); - productid[1] = inb(TPM_DATA); - outb(IDPDH, TPM_ADDR); - productid[0] = inb(TPM_DATA); - outb(CHIP_ID1, TPM_ADDR); - version[1] = inb(TPM_DATA); - outb(CHIP_ID2, TPM_ADDR); - version[0] = inb(TPM_DATA); - - if ((vendorid[0] << 8 | vendorid[1]) == (TCPA_INFINEON_DEV_VEN_VALUE)) { - - /* read IO-ports from TPM */ - outb(IOLIMH, TPM_ADDR); - ioh = inb(TPM_DATA); - outb(IOLIML, TPM_ADDR); - iol = inb(TPM_DATA); - tpm_inf.base = (ioh << 8) | iol; + outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); + outb(IDVENL, TPM_INF_ADDR); + vendorid[1] = inb(TPM_INF_DATA); + outb(IDVENH, TPM_INF_ADDR); + vendorid[0] = inb(TPM_INF_DATA); + outb(IDPDL, TPM_INF_ADDR); + productid[1] = inb(TPM_INF_DATA); + outb(IDPDH, TPM_INF_ADDR); + productid[0] = inb(TPM_INF_DATA); + outb(CHIP_ID1, TPM_INF_ADDR); + version[1] = inb(TPM_INF_DATA); + outb(CHIP_ID2, TPM_INF_ADDR); + version[0] = inb(TPM_INF_DATA); + + switch ((productid[0] << 8) | productid[1]) { + case 6: + sprintf(chipname, " (SLD 9630 TT 1.1)"); + break; + case 11: + sprintf(chipname, " (SLB 9635 TT 1.2)"); + break; + default: + sprintf(chipname, " (unknown chip)"); + break; + } + chipname[19] = 0; + + if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { if (tpm_inf.base == 0) { - dev_err(&pci_dev->dev, "No IO-ports set!\n"); + dev_err(&pci_dev->dev, "No IO-ports found!\n"); pci_disable_device(pci_dev); - return -ENODEV; + return -EIO; + } + /* configure TPM with IO-ports */ + outb(IOLIMH, TPM_INF_ADDR); + outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); + outb(IOLIML, TPM_INF_ADDR); + outb((tpm_inf.base & 0xff), TPM_INF_DATA); + + /* control if IO-ports are set correctly */ + outb(IOLIMH, TPM_INF_ADDR); + ioh = inb(TPM_INF_DATA); + outb(IOLIML, TPM_INF_ADDR); + iol = inb(TPM_INF_DATA); + + if ((ioh << 8 | iol) != tpm_inf.base) { + dev_err(&pci_dev->dev, + "Could not set IO-ports to %04x\n", + tpm_inf.base); + pci_disable_device(pci_dev); + return -EIO; } /* activate register */ - outb(TPM_DAR, TPM_ADDR); - outb(0x01, TPM_DATA); - outb(DISABLE_REGISTER_PAIR, TPM_ADDR); + outb(TPM_DAR, TPM_INF_ADDR); + outb(0x01, TPM_INF_DATA); + outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); /* disable RESET, LP and IRQC */ outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); /* Finally, we're done, print some infos */ dev_info(&pci_dev->dev, "TPM found: " + "config base 0x%x, " "io base 0x%x, " "chip version %02x%02x, " "vendor id %x%x (Infineon), " "product id %02x%02x" "%s\n", + TPM_INF_ADDR, tpm_inf.base, version[0], version[1], vendorid[0], vendorid[1], - productid[0], productid[1], ((productid[0] == 0) - && (productid[1] == - 6)) ? - " (SLD 9630 TT 1.1)" : ""); + productid[0], productid[1], chipname); rc = tpm_register_hardware(pci_dev, &tpm_inf); if (rc < 0) { @@ -462,6 +528,6 @@ module_init(init_inf); module_exit(cleanup_inf); MODULE_AUTHOR("Marcel Selhorst "); -MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT"); -MODULE_VERSION("1.4"); +MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); +MODULE_VERSION("1.5"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From e6cb99413da42af413c11a394538ddc8b9d201e1 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 5 Aug 2005 11:59:34 -0700 Subject: [PATCH] fix voyager compile after machine_emergency_restart breakage [PATCH] i386: Implement machine_emergency_reboot introduced this new function into arch/i386/reboot.c. However, subarchitectures are entitled to implement their own copies of reboot.c from which this new function is now missing. It looks like visws will also need a similar fixup Signed-off-by: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mach-voyager/voyager_basic.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c index b3eda46e0fe9..62d0d9bf3fc0 100644 --- a/arch/i386/mach-voyager/voyager_basic.c +++ b/arch/i386/mach-voyager/voyager_basic.c @@ -278,6 +278,13 @@ machine_restart(char *cmd) } } +void +machine_emergency_restart(void) +{ + /*for now, just hook this to a warm restart */ + machine_restart(NULL); +} + void mca_nmi_hook(void) { -- cgit v1.2.3 From c7546f8f03f5a4fa612605b6be930234d6026860 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 5 Aug 2005 11:59:35 -0700 Subject: [PATCH] Fix hugepage crash on failing mmap() This patch fixes a crash in the hugepage code. unmap_hugepage_area() was assuming that (due to prefault) PTEs must exist for all the area in question. However, this may not be the case, if mmap() encounters an error before the prefault and calls unmap_region() to clean up any partial mapping. Depending on the hugepage configuration, this crash can be triggered by an unpriveleged user. Signed-off-by: David Gibson Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index fbd1111ea119..6bf720bc662c 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -301,6 +301,7 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, { struct mm_struct *mm = vma->vm_mm; unsigned long address; + pte_t *ptep; pte_t pte; struct page *page; @@ -309,9 +310,17 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, BUG_ON(end & ~HPAGE_MASK); for (address = start; address < end; address += HPAGE_SIZE) { - pte = huge_ptep_get_and_clear(mm, address, huge_pte_offset(mm, address)); + ptep = huge_pte_offset(mm, address); + if (! ptep) + /* This can happen on truncate, or if an + * mmap() is aborted due to an error before + * the prefault */ + continue; + + pte = huge_ptep_get_and_clear(mm, address, ptep); if (pte_none(pte)) continue; + page = pte_page(pte); put_page(page); } -- cgit v1.2.3 From ba02508248e90a9d696aebd18b48a3290235b53c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 5 Aug 2005 13:28:11 -0700 Subject: [PATCH] blk: fix tag shrinking (revive real_max_size) My patch in commit fa72b903f75e4f0f0b2c2feed093005167da4023 incorrectly removed blk_queue_tag->real_max_depth. The original resize implementation was incorrect in the following points. * actual allocation size of tag_index was shorter than real_max_size, but assumed to be of the same size, possibly causing memory access beyond the allocated area. * bits in tag_map between max_deptn and real_max_depth were initialized to 1's, making the tags permanently reserved. In an attempt to fix above two bugs, I had removed allocation optimization in init_tag_map and real_max_size. Tag map/index were allocated and freed immediately during resize. Unfortunately, I wasn't considering that tag map/index can be resized dynamically with tags beyond new_depth active. This led to accessing freed area after shrinking tags and led to the following bug reporting thread on linux-scsi. http://marc.theaimsgroup.com/?l=linux-scsi&m=112319898111885&w=2 To fix the problem, I've revived real_max_depth without allocation optimization in init_tag_map, and Andrew Vasquez confirmed that the problem was fixed. As Jens is not going to be available for a week, he asked me to make sure that this patch reaches you. http://marc.theaimsgroup.com/?l=linux-scsi&m=112325778530886&w=2 Also, a comment was added to make sure that real_max_size is needed for dynamic shrinking. Signed-off-by: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/ll_rw_blk.c | 18 +++++++++++++++--- include/linux/blkdev.h | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 692a5fced76e..3c818544475e 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -719,7 +719,7 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag) { struct blk_queue_tag *bqt = q->queue_tags; - if (unlikely(bqt == NULL || tag >= bqt->max_depth)) + if (unlikely(bqt == NULL || tag >= bqt->real_max_depth)) return NULL; return bqt->tag_index[tag]; @@ -798,6 +798,7 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) memset(tag_index, 0, depth * sizeof(struct request *)); memset(tag_map, 0, nr_ulongs * sizeof(unsigned long)); + tags->real_max_depth = depth; tags->max_depth = depth; tags->tag_index = tag_index; tags->tag_map = tag_map; @@ -871,12 +872,23 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth) if (!bqt) return -ENXIO; + /* + * if we already have large enough real_max_depth. just + * adjust max_depth. *NOTE* as requests with tag value + * between new_depth and real_max_depth can be in-flight, tag + * map can not be shrunk blindly here. + */ + if (new_depth <= bqt->real_max_depth) { + bqt->max_depth = new_depth; + return 0; + } + /* * save the old state info, so we can copy it back */ tag_index = bqt->tag_index; tag_map = bqt->tag_map; - max_depth = bqt->max_depth; + max_depth = bqt->real_max_depth; if (init_tag_map(q, bqt, new_depth)) return -ENOMEM; @@ -913,7 +925,7 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq) BUG_ON(tag == -1); - if (unlikely(tag >= bqt->max_depth)) + if (unlikely(tag >= bqt->real_max_depth)) /* * This can happen after tag depth has been reduced. * FIXME: how about a warning or info message here? diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 0881b5cdee3d..19bd8e7e11bf 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -301,6 +301,7 @@ struct blk_queue_tag { struct list_head busy_list; /* fifo list of busy tags */ int busy; /* current depth */ int max_depth; /* what we will send to device */ + int real_max_depth; /* what the array can hold */ atomic_t refcnt; /* map can be shared */ }; -- cgit v1.2.3 From 00a5dfdb93f74e4d95fb0d83c890728e331f8810 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 5 Aug 2005 23:05:27 +0200 Subject: [PATCH] Fix semundo lock leakage semundo->lock can leak if semundo->refcount goes from 2 to 1 while another thread has it locked. This causes major problems for PREEMPT kernels. The simplest fix for now is to undo the single-thread optimization. This bug was found via relentless testing by Dominik Karall. Signed-off-by: Ingo Molnar Signed-off-by: Linus Torvalds --- ipc/sem.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ipc/sem.c b/ipc/sem.c index 7e8a25c82ef3..70975ce0784a 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -895,7 +895,7 @@ static inline void lock_semundo(void) struct sem_undo_list *undo_list; undo_list = current->sysvsem.undo_list; - if ((undo_list != NULL) && (atomic_read(&undo_list->refcnt) != 1)) + if (undo_list) spin_lock(&undo_list->lock); } @@ -915,7 +915,7 @@ static inline void unlock_semundo(void) struct sem_undo_list *undo_list; undo_list = current->sysvsem.undo_list; - if ((undo_list != NULL) && (atomic_read(&undo_list->refcnt) != 1)) + if (undo_list) spin_unlock(&undo_list->lock); } @@ -943,9 +943,7 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp) if (undo_list == NULL) return -ENOMEM; memset(undo_list, 0, size); - /* don't initialize unodhd->lock here. It's done - * in copy_semundo() instead. - */ + spin_lock_init(&undo_list->lock); atomic_set(&undo_list->refcnt, 1); current->sysvsem.undo_list = undo_list; } @@ -1231,8 +1229,6 @@ int copy_semundo(unsigned long clone_flags, struct task_struct *tsk) error = get_undo_list(&undo_list); if (error) return error; - if (atomic_read(&undo_list->refcnt) == 1) - spin_lock_init(&undo_list->lock); atomic_inc(&undo_list->refcnt); tsk->sysvsem.undo_list = undo_list; } else -- cgit v1.2.3 From 4aad724d3e52238e1ce005f166fbba5b4072a7f6 Mon Sep 17 00:00:00 2001 From: Tim Yamin Date: Mon, 25 Jul 2005 23:16:13 +0100 Subject: [PATCH] Update in-kernel zlib routines These bugs have been fixed in the standard zlib for a while. See for example a) http://sources.redhat.com/ml/bug-gnu-utils/1999-06/msg00183.html b) http://bugs.gentoo.org/show_bug.cgi?id=94584 Signed-off-by: Tim Yamin Signed-off-by: Tavis Ormandy Signed-off-by: Linus Torvalds --- arch/ppc64/boot/zlib.c | 3 ++- lib/inflate.c | 16 +++++++++------- lib/zlib_inflate/inftrees.c | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/arch/ppc64/boot/zlib.c b/arch/ppc64/boot/zlib.c index 9d5e4e9832d2..78837e884b8b 100644 --- a/arch/ppc64/boot/zlib.c +++ b/arch/ppc64/boot/zlib.c @@ -1307,7 +1307,7 @@ local int huft_build( { *t = (inflate_huft *)Z_NULL; *m = 0; - return Z_OK; + return Z_DATA_ERROR; } @@ -1351,6 +1351,7 @@ local int huft_build( if ((j = *p++) != 0) v[x[j]++] = i; } while (++i < n); + n = x[g]; /* set n to length of v */ /* Generate the Huffman codes and for each, make the table entries */ diff --git a/lib/inflate.c b/lib/inflate.c index 75e7d303c72e..6db6e98d1637 100644 --- a/lib/inflate.c +++ b/lib/inflate.c @@ -326,7 +326,7 @@ DEBG("huft1 "); { *t = (struct huft *)NULL; *m = 0; - return 0; + return 2; } DEBG("huft2 "); @@ -374,6 +374,7 @@ DEBG("huft5 "); if ((j = *p++) != 0) v[x[j]++] = i; } while (++i < n); + n = x[g]; /* set n to length of v */ DEBG("h6 "); @@ -410,12 +411,13 @@ DEBG1("1 "); DEBG1("2 "); f -= a + 1; /* deduct codes from patterns left */ xp = c + k; - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } } DEBG1("3 "); z = 1 << j; /* table entries for j-bit table */ diff --git a/lib/zlib_inflate/inftrees.c b/lib/zlib_inflate/inftrees.c index 874950ec4858..c5f66fbb0dd0 100644 --- a/lib/zlib_inflate/inftrees.c +++ b/lib/zlib_inflate/inftrees.c @@ -141,7 +141,7 @@ static int huft_build( { *t = NULL; *m = 0; - return Z_OK; + return Z_DATA_ERROR; } -- cgit v1.2.3 From 534afb90a9cd0b9643f62d660c164e1d924f39cf Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 5 Aug 2005 16:10:10 -0700 Subject: [PATCH] ppc32: fix ppc440 pagetable attributes This patch fixes a bug in the PPC440 pagetable attributes that breaks swap support. It also adds some notes on the PPC440 attribute fields. Signed-off-by: Geoff Levand for CELF Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-ppc/pgtable.h | 52 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index 4d4b20c9de78..c41c7958ea1f 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -202,18 +202,64 @@ extern unsigned long ioremap_bot, ioremap_base; * * Note that these bits preclude future use of a page size * less than 4KB. + * + * + * PPC 440 core has following TLB attribute fields; + * + * TLB1: + * 0 1 2 3 4 ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + * RPN................................. - - - - - - ERPN....... + * + * TLB2: + * 0 1 2 3 4 ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + * - - - - - - U0 U1 U2 U3 W I M G E - UX UW UR SX SW SR + * + * There are some constrains and options, to decide mapping software bits + * into TLB entry. + * + * - PRESENT *must* be in the bottom three bits because swap cache + * entries use the top 29 bits for TLB2. + * + * - FILE *must* be in the bottom three bits because swap cache + * entries use the top 29 bits for TLB2. + * + * - CACHE COHERENT bit (M) has no effect on PPC440 core, because it + * doesn't support SMP. So we can use this as software bit, like + * DIRTY. + * + * PPC Book-E Linux implementation uses PPC HW PTE bit field definition, + * even it doesn't have HW PTE. 0-11th LSB of PTE stand for memory + * protection-related function. (See PTE structure in include/asm-ppc/mmu.h) + * Definition of _PAGE_XXX in "include/asm-ppc/pagetable.h" stands for + * above bits. Note that those bits values are CPU dependent, not + * architecture. + * + * Kernel PTE entry holds arch-dependent swp_entry structure under certain + * situation. In other words, in such situation, some portion of PTE bits + * are used as swp_entry. In PPC implementation, 3-24th LSB are shared with + * swp_entry, however 0-2nd three LSB still hold protection values. + * That means three protection bits are reserved for both PTE and SWAP + * entry at the most three LSBs. + * + * There are three protection bits available for SWAP entry; + * _PAGE_PRESENT + * _PAGE_FILE + * _PAGE_HASHPTE (if HW has) + * + * So those three bits have to be inside of 0-2nd LSB of PTE. + * */ + #define _PAGE_PRESENT 0x00000001 /* S: PTE valid */ #define _PAGE_RW 0x00000002 /* S: Write permission */ -#define _PAGE_DIRTY 0x00000004 /* S: Page dirty */ +#define _PAGE_FILE 0x00000004 /* S: nonlinear file mapping */ #define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ #define _PAGE_HWWRITE 0x00000010 /* H: Dirty & RW */ #define _PAGE_HWEXEC 0x00000020 /* H: Execute permission */ #define _PAGE_USER 0x00000040 /* S: User page */ #define _PAGE_ENDIAN 0x00000080 /* H: E bit */ #define _PAGE_GUARDED 0x00000100 /* H: G bit */ -#define _PAGE_COHERENT 0x00000200 /* H: M bit */ -#define _PAGE_FILE 0x00000400 /* S: nonlinear file mapping */ +#define _PAGE_DIRTY 0x00000200 /* S: Page dirty */ #define _PAGE_NO_CACHE 0x00000400 /* H: I bit */ #define _PAGE_WRITETHRU 0x00000800 /* H: W bit */ -- cgit v1.2.3 From cad0f6270c0bae5bcae6af3c7ac7bd3ae5d9b618 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 12:36:36 +0200 Subject: [Bluetooth] Send HCI_Reset for Kensington dongle The Kensington Bluetooth USB adapter is based on a Broadcom chip with the HID proxy support. To initialize these kind of devices correctly it is necessary to send HCI_Reset as the first command. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_usb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index b120ecf7b8c9..e8bad41da37f 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -110,6 +110,9 @@ static struct usb_device_id blacklist_ids[] = { /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, + /* Kensington Bluetooth USB adapter */ + { USB_DEVICE(0x047d, 0x105d), .driver_info = HCI_RESET }, + /* ISSC Bluetooth Adapter v3.1 */ { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, -- cgit v1.2.3 From dcc365d8f28d6a2332fa37e64d669858a8d017e8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 12:36:42 +0200 Subject: [Bluetooth] Revert session reference counting fix The fix for the reference counting problem of the signal DLC introduced a race condition which leads to an oops. The reason for it is not fully understood by now and so revert this fix, because the reference counting problem is not crashing the RFCOMM layer and its appearance it rare. Signed-off-by: Marcel Holtmann --- net/bluetooth/rfcomm/core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index e9e6fda66f1a..27bf5047cd33 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -389,8 +389,6 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) rfcomm_dlc_unlock(d); skb_queue_purge(&d->tx_queue); - rfcomm_session_put(s); - rfcomm_dlc_unlink(d); } @@ -600,8 +598,6 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst goto failed; } - rfcomm_session_hold(s); - s->initiator = 1; bacpy(&addr.l2_bdaddr, dst); -- cgit v1.2.3 From e9a3e671c09d419f29710d8620ed916d3bf7d7ab Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 12:36:47 +0200 Subject: [Bluetooth] Kill redundant NULL checks before kfree() There's no need to check for NULL before calling kfree() on a pointer. Signed-off-by: Jesper Juhl Signed-off-by: Marcel Holtmann --- drivers/bluetooth/bpa10x.c | 7 ++----- drivers/bluetooth/hci_usb.c | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 2771c861f185..f696da6f417b 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -367,11 +367,8 @@ static inline void bpa10x_free_urb(struct urb *urb) if (!urb) return; - if (urb->setup_packet) - kfree(urb->setup_packet); - - if (urb->transfer_buffer) - kfree(urb->transfer_buffer); + kfree(urb->setup_packet); + kfree(urb->transfer_buffer); usb_free_urb(urb); } diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index e8bad41da37f..319871ca9f9f 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -390,10 +390,8 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb) urb = &_urb->urb; BT_DBG("%s freeing _urb %p type %d urb %p", husb->hdev->name, _urb, _urb->type, urb); - if (urb->setup_packet) - kfree(urb->setup_packet); - if (urb->transfer_buffer) - kfree(urb->transfer_buffer); + kfree(urb->setup_packet); + kfree(urb->transfer_buffer); _urb_free(_urb); } -- cgit v1.2.3 From 66e8b6c31b9254243afaac8af4135e84e11dd38e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 12:36:51 +0200 Subject: [Bluetooth] Remove unused functions and cleanup symbol exports This patch removes the unused bt_dump() function and it also removes its BT_DMP macro. It also unexports the hci_dev_get(), hci_send_cmd() and hci_si_event() functions. Signed-off-by: Adrian Bunk Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcsp.c | 2 -- drivers/bluetooth/hci_h4.c | 5 ----- drivers/bluetooth/hci_ldisc.c | 2 -- drivers/bluetooth/hci_usb.c | 2 -- include/net/bluetooth/bluetooth.h | 8 -------- net/bluetooth/hci_core.c | 2 -- net/bluetooth/hci_event.c | 1 - net/bluetooth/lib.c | 25 ------------------------- 8 files changed, 47 deletions(-) diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index c0ed213fc857..858fddb046de 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -58,8 +58,6 @@ #ifndef CONFIG_BT_HCIUART_DEBUG #undef BT_DBG #define BT_DBG( A... ) -#undef BT_DMP -#define BT_DMP( A... ) #endif static int hciextn = 1; diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index ade94a57bb11..533323b60e63 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -57,8 +57,6 @@ #ifndef CONFIG_BT_HCIUART_DEBUG #undef BT_DBG #define BT_DBG( A... ) -#undef BT_DMP -#define BT_DMP( A... ) #endif /* Initialize protocol */ @@ -125,7 +123,6 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) BT_DBG("len %d room %d", len, room); if (!len) { - BT_DMP(h4->rx_skb->data, h4->rx_skb->len); hci_recv_frame(h4->rx_skb); } else if (len > room) { BT_ERR("Data length is too large"); @@ -169,8 +166,6 @@ static int h4_recv(struct hci_uart *hu, void *data, int count) case H4_W4_DATA: BT_DBG("Complete data"); - BT_DMP(h4->rx_skb->data, h4->rx_skb->len); - hci_recv_frame(h4->rx_skb); h4->rx_state = H4_W4_PACKET_TYPE; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index f766bc22c6bb..90be2eae52e0 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -57,8 +57,6 @@ #ifndef CONFIG_BT_HCIUART_DEBUG #undef BT_DBG #define BT_DBG( A... ) -#undef BT_DMP -#define BT_DMP( A... ) #endif static int reset = 0; diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 319871ca9f9f..657719b8254f 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -57,8 +57,6 @@ #ifndef CONFIG_BT_HCIUSB_DEBUG #undef BT_DBG #define BT_DBG(D...) -#undef BT_DMP -#define BT_DMP(D...) #endif #ifndef CONFIG_BT_HCIUSB_ZERO_PACKET diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 42a84c53678b..06b24f637026 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -57,12 +57,6 @@ #define BT_DBG(fmt, arg...) printk(KERN_INFO "%s: " fmt "\n" , __FUNCTION__ , ## arg) #define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __FUNCTION__ , ## arg) -#ifdef HCI_DATA_DUMP -#define BT_DMP(buf, len) bt_dump(__FUNCTION__, buf, len) -#else -#define BT_DMP(D...) -#endif - extern struct proc_dir_entry *proc_bt; /* Connection and socket states */ @@ -174,8 +168,6 @@ static inline int skb_frags_no(struct sk_buff *skb) return n; } -void bt_dump(char *pref, __u8 *buf, int count); - int bt_err(__u16 code); #endif /* __BLUETOOTH_H */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index fb5524365bc2..ffa26c10bfe8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -299,7 +299,6 @@ struct hci_dev *hci_dev_get(int index) read_unlock(&hci_dev_list_lock); return hdev; } -EXPORT_SYMBOL(hci_dev_get); /* ---- Inquiry support ---- */ static void inquiry_cache_flush(struct hci_dev *hdev) @@ -1042,7 +1041,6 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p return 0; } -EXPORT_SYMBOL(hci_send_cmd); /* Get data from the previously sent command */ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index c4b592b4ef10..26050d13fb47 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1040,4 +1040,3 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) hci_send_to_sock(hdev, skb); kfree_skb(skb); } -EXPORT_SYMBOL(hci_si_event); diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c index 9efb0a093612..ee6a66979913 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c @@ -34,31 +34,6 @@ #include -void bt_dump(char *pref, __u8 *buf, int count) -{ - char *ptr; - char line[100]; - unsigned int i; - - printk(KERN_INFO "%s: dump, len %d\n", pref, count); - - ptr = line; - *ptr = 0; - for (i = 0; i < count; i++) { - ptr += sprintf(ptr, " %2.2X", buf[i]); - - if (i && !((i + 1) % 20)) { - printk(KERN_INFO "%s:%s\n", pref, line); - ptr = line; - *ptr = 0; - } - } - - if (line[0]) - printk(KERN_INFO "%s:%s\n", pref, line); -} -EXPORT_SYMBOL(bt_dump); - void baswap(bdaddr_t *dst, bdaddr_t *src) { unsigned char *d = (unsigned char *) dst; -- cgit v1.2.3 From 576c7d858f36cab6110b29db7b53964d5132cf30 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 12:36:54 +0200 Subject: [Bluetooth] Add direction and timestamp to stack internal events This patch changes the direction to incoming and adds the timestamp to all stack internal events. Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 26050d13fb47..46367bd129c3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1035,6 +1035,9 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) ev->type = type; memcpy(ev->data, data, dlen); + bt_cb(skb)->incoming = 1; + do_gettimeofday(&skb->stamp); + skb->pkt_type = HCI_EVENT_PKT; skb->dev = (void *) hdev; hci_send_to_sock(hdev, skb); -- cgit v1.2.3 From 6fc0b4a7a73a81e74d0004732df358f4f9975be2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 6 Aug 2005 06:33:15 -0700 Subject: [IPSEC]: Restrict socket policy loading to CAP_NET_ADMIN. The interface needs much redesigning if we wish to allow normal users to do this in some way. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/ip_sockglue.c | 3 +++ net/ipv6/ipv6_sockglue.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index fc7c481d0d79..ff4bd067b397 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -848,6 +848,9 @@ mc_msf_out: case IP_IPSEC_POLICY: case IP_XFRM_POLICY: + err = -EPERM; + if (!capable(CAP_NET_ADMIN)) + break; err = xfrm_user_policy(sk, optname, optval, optlen); break; diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index f3ef4c38d315..3bc144a79fa5 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -504,6 +504,9 @@ done: break; case IPV6_IPSEC_POLICY: case IPV6_XFRM_POLICY: + retv = -EPERM; + if (!capable(CAP_NET_ADMIN)) + break; retv = xfrm_user_policy(sk, optname, optval, optlen); break; -- cgit v1.2.3 From 7d3f4c97723c4ec4e5d85e6e70084b02e6be8788 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 6 Aug 2005 06:35:48 -0700 Subject: [TG3]: Save initial PCI state before registering the netdevice. Else on SMP systems it is possible for hotplug to execute, invoke tg3_open(), and end up loading the uninitialized PCI register save area into the card. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 201a550f0bcc..368b8fb14023 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -66,8 +66,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.34" -#define DRV_MODULE_RELDATE "July 25, 2005" +#define DRV_MODULE_VERSION "3.35" +#define DRV_MODULE_RELDATE "August 6, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -10421,6 +10421,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_coal(tp); + /* Now that we have fully setup the chip, save away a snapshot + * of the PCI config space. We need to restore this after + * GRC_MISC_CFG core clock resets and some resume events. + */ + pci_save_state(tp->pdev); + err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "Cannot register net device, " @@ -10430,12 +10436,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); - /* Now that we have fully setup the chip, save away a snapshot - * of the PCI config space. We need to restore this after - * GRC_MISC_CFG core clock resets and some resume events. - */ - pci_save_state(tp->pdev); - printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", dev->name, tp->board_part_number, -- cgit v1.2.3 From 021a52ac70802a94e699badb52af9d0fa728d5cd Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Sat, 6 Aug 2005 07:21:06 -0700 Subject: [PATCH] ppc32: ppc440 pagetable attributes (comments updates) Here's an incremental patch with comment updates and some additional grammar cleanups. Signed-off-by: Matt Porter Signed-off-by: Linus Torvalds --- include/asm-ppc/pgtable.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index c41c7958ea1f..92f30b28b252 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -227,21 +227,21 @@ extern unsigned long ioremap_bot, ioremap_base; * doesn't support SMP. So we can use this as software bit, like * DIRTY. * - * PPC Book-E Linux implementation uses PPC HW PTE bit field definition, - * even it doesn't have HW PTE. 0-11th LSB of PTE stand for memory - * protection-related function. (See PTE structure in include/asm-ppc/mmu.h) - * Definition of _PAGE_XXX in "include/asm-ppc/pagetable.h" stands for - * above bits. Note that those bits values are CPU dependent, not - * architecture. + * With the PPC 44x Linux implementation, the 0-11th LSBs of the PTE are used + * for memory protection related functions (see PTE structure in + * include/asm-ppc/mmu.h). The _PAGE_XXX definitions in this file map to the + * above bits. Note that the bit values are CPU specific, not architecture + * specific. * - * Kernel PTE entry holds arch-dependent swp_entry structure under certain - * situation. In other words, in such situation, some portion of PTE bits - * are used as swp_entry. In PPC implementation, 3-24th LSB are shared with - * swp_entry, however 0-2nd three LSB still hold protection values. - * That means three protection bits are reserved for both PTE and SWAP - * entry at the most three LSBs. + * The kernel PTE entry holds an arch-dependent swp_entry structure under + * certain situations. In other words, in such situations some portion of + * the PTE bits are used as a swp_entry. In the PPC implementation, the + * 3-24th LSB are shared with swp_entry, however the 0-2nd three LSB still + * hold protection values. That means the three protection bits are + * reserved for both PTE and SWAP entry at the most significant three + * LSBs. * - * There are three protection bits available for SWAP entry; + * There are three protection bits available for SWAP entry: * _PAGE_PRESENT * _PAGE_FILE * _PAGE_HASHPTE (if HW has) -- cgit v1.2.3 From 243393c90f2b7cb781fd794e22786e9c8547901a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 6 Aug 2005 09:39:57 -0700 Subject: Add fakey 'deflateBound()' function to the in-kernel zlib routines It's not the real deflateBound() in newer zlib libraries, partly because the upcoming usage of it won't have the "stream" available, so we can't have the same interfaces anyway. --- include/linux/zlib.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/zlib.h b/include/linux/zlib.h index 850076ea14d3..74f7b78c22d2 100644 --- a/include/linux/zlib.h +++ b/include/linux/zlib.h @@ -506,6 +506,11 @@ extern int zlib_deflateReset (z_streamp strm); stream state was inconsistent (such as zalloc or state being NULL). */ +static inline unsigned long deflateBound(unsigned long s) +{ + return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11; +} + extern int zlib_deflateParams (z_streamp strm, int level, int strategy); /* Dynamically update the compression level and compression strategy. The -- cgit v1.2.3 From fab5a60a29f98f17256a4183e34a414f6db67569 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 6 Aug 2005 09:42:06 -0700 Subject: Check input buffer size in zisofs This uses the new deflateBound() thing to sanity-check the input to the zlib decompressor before we even bother to start reading in the blocks. Problem noted by Tim Yamin --- fs/isofs/compress.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index 34a44e451689..4917315db732 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c @@ -129,8 +129,14 @@ static int zisofs_readpage(struct file *file, struct page *page) cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask))); brelse(bh); + if (cstart > cend) + goto eio; + csize = cend-cstart; + if (csize > deflateBound(1UL << zisofs_block_shift)) + goto eio; + /* Now page[] contains an array of pages, any of which can be NULL, and the locks on which we hold. We should now read the data and release the pages. If the pages are NULL the decompressed data -- cgit v1.2.3 From d8588ee5b87226d96e07add42027246746357fe3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 6 Aug 2005 09:44:37 -0700 Subject: ppc: Export __handle_mm_fault for MOL When we did the handle_mm_fault cleanup and get_user_page() race fixes, handle_mm_fault turned into an inline function that called the real __handle_mm_fault() code. The export needed for MOL on ppc wasn't updated to match the new world order, though. Turn it into a GPL export while at it, since this is all about internal interfaces and MOL is GPL'd anwyay. --- arch/ppc/kernel/ppc_ksyms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index d59ad07de8e7..e7d40cc6c1b6 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -324,7 +324,7 @@ EXPORT_SYMBOL(__res); EXPORT_SYMBOL(next_mmu_context); EXPORT_SYMBOL(set_context); -EXPORT_SYMBOL(handle_mm_fault); /* For MOL */ +EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */ EXPORT_SYMBOL(disarm_decr); #ifdef CONFIG_PPC_STD_MMU extern long mol_trampoline; -- cgit v1.2.3 From 094528a7fb3f75a83673e5cc3271fd466f2e278d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 6 Aug 2005 13:42:45 -0600 Subject: [PATCH] i386 voyager: Add machine_shutdown Here is one more bit of breakage my x86 sub-architecture confusion caused. Add machine_shutdown to voyager so it will compile with CONFIG_KEXEC. Signed-off-by: Linus Torvalds --- arch/i386/mach-voyager/voyager_basic.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c index 62d0d9bf3fc0..c6384061328a 100644 --- a/arch/i386/mach-voyager/voyager_basic.c +++ b/arch/i386/mach-voyager/voyager_basic.c @@ -251,6 +251,12 @@ kb_wait(void) break; } +void +machine_shutdown(void) +{ + /* Architecture specific shutdown needed before a kexec */ +} + void machine_restart(char *cmd) { -- cgit v1.2.3 From 36cf446c2c4be6bae01517ea539dcebaf85c9fdf Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 6 Aug 2005 13:45:10 -0600 Subject: [PATCH] i386 visws: Add machine_shutdown and emergency_restart Another x86 subarchitecture bit I missed. This adds both machine_emergency_restart missed in my reboot fixes and machine_shutdown needed for kexec support. Signed-off-by: Linus Torvalds --- arch/i386/mach-visws/reboot.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/i386/mach-visws/reboot.c b/arch/i386/mach-visws/reboot.c index 9e9296676f93..5d73e042ed0a 100644 --- a/arch/i386/mach-visws/reboot.c +++ b/arch/i386/mach-visws/reboot.c @@ -9,12 +9,15 @@ void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); -void machine_restart(char * __unused) +void machine_shutdown(void) { #ifdef CONFIG_SMP smp_send_stop(); #endif +} +void machine_emergency_restart(void) +{ /* * Visual Workstations restart after this * register is poked on the PIIX4 @@ -22,6 +25,12 @@ void machine_restart(char * __unused) outb(PIIX4_RESET_VAL, PIIX4_RESET_PORT); } +void machine_restart(char * __unused) +{ + machine_shutdown(); + machine_emergency_restart(); +} + void machine_power_off(void) { unsigned short pm_status; -- cgit v1.2.3 From 0d317fb72fe3cf0f611608cf3a3015bbe6cd2a66 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 6 Aug 2005 13:47:36 -0600 Subject: [PATCH] x86_64 bootmem: sparse_mem/kexec merge bug. When the sparse mem changes and the kexec changes were merged into setup.c they came in, in the wrong order. This patch changes the order so we don't run sparse_init which uses the bootmem allocator until we all of the reserve_bootmem calls has been made. Signed-off-by: Eric W. Biederman Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 0aa526298e92..116a491e2961 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -645,15 +645,15 @@ void __init setup_arch(char **cmdline_p) } } #endif - - sparse_init(); - #ifdef CONFIG_KEXEC if (crashk_res.start != crashk_res.end) { reserve_bootmem(crashk_res.start, crashk_res.end - crashk_res.start + 1); } #endif + + sparse_init(); + paging_init(); check_ioapic(); -- cgit v1.2.3 From fc1df37e3b195cb73ecb14c30d41b7aace3f844a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 7 Aug 2005 14:20:26 +0100 Subject: [PATCH] ARM: Make sa1100fb_display_dma_period() an inline function This function produces a warning when CPU_FREQ=n. Since it's a very simple calculation, make it inline instead of adding preprocessor directives around it. Signed-off-by: Russell King --- drivers/video/sa1100fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 2d29db7ef800..beeec7b51425 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -598,7 +598,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, * requests for the LCD controller. If we hit this, it means we're * doing nothing but LCD DMA. */ -static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var) +static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var) { /* * Period = pixclock * bits_per_byte * bytes_per_transfer -- cgit v1.2.3 From 71abe99980e6d7ff8aee8acc7da817b3ad7d8a89 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 7 Aug 2005 14:23:42 +0100 Subject: [PATCH] ARM: switch fd1772.c from sleep_on to wait_event Doesn't make the local irq disabling around it less buggy, but at least we replace the offender with the right kind of primitive. Signed-off-by: Christoph Hellwig Signed-off-by: Russell King --- drivers/acorn/block/fd1772.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c index 3cd2e968e96c..c0a37d98b4f3 100644 --- a/drivers/acorn/block/fd1772.c +++ b/drivers/acorn/block/fd1772.c @@ -1283,8 +1283,7 @@ static void do_fd_request(request_queue_t* q) if (fdc_busy) return; save_flags(flags); cli(); - while (fdc_busy) - sleep_on(&fdc_wait); + wait_event(fdc_wait, !fdc_busy); fdc_busy = 1; ENABLE_IRQ(); restore_flags(flags); -- cgit v1.2.3 From cf7bee5a0bf270a4eace0be39329d6ac0136cc47 Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Sun, 7 Aug 2005 13:49:59 +0400 Subject: [PATCH] Fix restore of 64-bit PCI BAR's For 64-bit BAR[i] only pci_dev->resource[i] is valid, ->resource[i+1] slot is unused and contains zeroes in all fields. So when we update a PCI BAR, all we need is just to check that we're going to update a _valid_ resource. Also make sure to write high bits - use "x >> 16 >> 16" (rather than the simpler ">> 32") to avoid warnings on 32-bit architectures where we're not going to have any high bits. Signed-off-by: Linus Torvalds --- drivers/pci/setup-res.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 878fd0a65c02..589486704ce3 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -33,6 +33,11 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) u32 new, check, mask; int reg; + /* Ignore resources for unimplemented BARs and unused resource slots + for 64 bit BARs. */ + if (!res->flags) + return; + pcibios_resource_to_bus(dev, ®ion, res); pr_debug(" got res [%lx:%lx] bus [%lx:%lx] flags %lx for " @@ -67,7 +72,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) if ((new & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) { - new = 0; /* currently everyone zeros the high address */ + new = region.start >> 16 >> 16; pci_write_config_dword(dev, reg + 4, new); pci_read_config_dword(dev, reg + 4, &check); if (check != new) { -- cgit v1.2.3 From d5172f263f76ca6d588f533c0989b22521fcbac2 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sun, 7 Aug 2005 09:42:07 -0700 Subject: [PATCH] x86_64: ignore machine checks from boot time Don't log machine check events left over from boot. Too many BIOSes leave bogus events in there. This unfortunately also makes it impossible to log events that caused a reboot. For people with non broken BIOS there is mce=bootlog Signed-off-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/x86_64/boot-options.txt | 5 +++++ arch/x86_64/kernel/mce.c | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index 476c0c22fbb7..678e8f192db2 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt @@ -6,6 +6,11 @@ only the AMD64 specific ones are listed here. Machine check mce=off disable machine check + mce=bootlog Enable logging of machine checks left over from booting. + Disabled by default because some BIOS leave bogus ones. + If your BIOS doesn't do that it's a good idea to enable though + to make sure you log even machine check events that result + in a reboot. nomce (for compatibility with i386): same as mce=off diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 3b267c91bb0c..8aa56736cde3 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -36,6 +36,7 @@ static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL }; static unsigned long console_logged; static int notify_user; static int rip_msr; +static int mce_bootlog; /* * Lockless MCE logging infrastructure. @@ -197,10 +198,11 @@ void do_machine_check(struct pt_regs * regs, long error_code) rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); mce_get_rip(&m, regs); - if (error_code != -1) + if (error_code >= 0) rdtscll(m.tsc); wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); - mce_log(&m); + if (error_code != -2) + mce_log(&m); /* Did this bank cause the exception? */ /* Assume that the bank with uncorrectable errors did it, @@ -315,7 +317,7 @@ static void mce_init(void *dummy) /* Log the machine checks left over from the previous reset. This also clears all registers */ - do_machine_check(NULL, -1); + do_machine_check(NULL, mce_bootlog ? -1 : -2); set_in_cr4(X86_CR4_MCE); @@ -476,11 +478,17 @@ static int __init mcheck_disable(char *str) } /* mce=off disables machine check. Note you can reenable it later - using sysfs */ + using sysfs. + mce=bootlog Log MCEs from before booting. Disabled by default to work + around buggy BIOS that leave bogus MCEs. */ static int __init mcheck_enable(char *str) { + if (*str == '=') + str++; if (!strcmp(str, "off")) mce_dont_init = 1; + else if (!strcmp(str, "bootlog")) + mce_bootlog = 1; else printk("mce= argument %s ignored. Please use /sys", str); return 0; -- cgit v1.2.3 From e525e153c7a99fc64af68e7f50a2660babd6752b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 7 Aug 2005 09:42:12 -0700 Subject: [PATCH] __bio_clone() dead comment Remove a very wrong comment. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/bio.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/bio.c b/fs/bio.c index 249dd6bb66c8..1f2d4649b188 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -248,17 +248,13 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src) { request_queue_t *q = bdev_get_queue(bio_src->bi_bdev); - memcpy(bio->bi_io_vec, bio_src->bi_io_vec, bio_src->bi_max_vecs * sizeof(struct bio_vec)); + memcpy(bio->bi_io_vec, bio_src->bi_io_vec, + bio_src->bi_max_vecs * sizeof(struct bio_vec)); bio->bi_sector = bio_src->bi_sector; bio->bi_bdev = bio_src->bi_bdev; bio->bi_flags |= 1 << BIO_CLONED; bio->bi_rw = bio_src->bi_rw; - - /* - * notes -- maybe just leave bi_idx alone. assume identical mapping - * for the clone - */ bio->bi_vcnt = bio_src->bi_vcnt; bio->bi_size = bio_src->bi_size; bio->bi_idx = bio_src->bi_idx; -- cgit v1.2.3 From 6c79d7260a8522a54374fa10dd2838eaef492cf2 Mon Sep 17 00:00:00 2001 From: Tom Duffy Date: Sun, 7 Aug 2005 09:42:16 -0700 Subject: [PATCH] Make visws compile again In file included from linux-2.6.13-rc5/arch/i386/kernel/timers/timer_pit.c:20: linux-2.6.13-rc5/include/asm-i386/mach-visws/do_timer.h: In function `do_timer_overflow': linux-2.6.13-rc5/include/asm-i386/mach-visws/do_timer.h:32: error: `i8259A_lock' undeclared (first use in this function) linux-2.6.13-rc5/include/asm-i386/mach-visws/do_timer.h:32: error: (Each undeclared identifier is reported only once linux-2.6.13-rc5/include/asm-i386/mach-visws/do_timer.h:32: error: for each function it appears in.) make[3]: *** [arch/i386/kernel/timers/timer_pit.o] Error 1 make[2]: *** [arch/i386/kernel/timers] Error 2 make[1]: *** [arch/i386/kernel] Error 2 make: *** [_all] Error 2 Signed-off-by: Tom Duffy Cc: Andrey Panin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-i386/mach-visws/do_timer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-i386/mach-visws/do_timer.h b/include/asm-i386/mach-visws/do_timer.h index 33acd50fd9a8..92d638fc8b11 100644 --- a/include/asm-i386/mach-visws/do_timer.h +++ b/include/asm-i386/mach-visws/do_timer.h @@ -1,6 +1,7 @@ /* defines for inline arch setup functions */ #include +#include #include "cobalt.h" static inline void do_timer_interrupt_hook(struct pt_regs *regs) -- cgit v1.2.3 From 46bdac99382dd36e2d8c36cfb35d879b5c136965 Mon Sep 17 00:00:00 2001 From: Tom Duffy Date: Sun, 7 Aug 2005 09:42:23 -0700 Subject: [PATCH] visws: linkage fix This patch add stubs to allow the visws subarch to link again. Signed-off-by: Tom Duffy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mach-visws/setup.c | 2 ++ arch/i386/pci/visws.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/i386/mach-visws/setup.c b/arch/i386/mach-visws/setup.c index 9f6d2d9b1be7..26ada6fc0d77 100644 --- a/arch/i386/mach-visws/setup.c +++ b/arch/i386/mach-visws/setup.c @@ -14,6 +14,8 @@ #include "cobalt.h" #include "piix4.h" +int no_broadcast; + char visws_board_type = -1; char visws_board_rev = -1; diff --git a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c index 314c933b6b8e..6c17433fdf7d 100644 --- a/arch/i386/pci/visws.c +++ b/arch/i386/pci/visws.c @@ -18,8 +18,10 @@ extern struct pci_raw_ops pci_direct_conf1; static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; } +static void pci_visws_disable_irq(struct pci_dev *dev) { } int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq; +void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq; void __init pcibios_penalize_isa_irq(int irq, int active) {} -- cgit v1.2.3 From 9ae5b3c703cce89a7d8ccf25fe16955ec6f016c0 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sun, 7 Aug 2005 09:42:24 -0700 Subject: [PATCH] remove linux/pagemap.h from linux/swap.h sparc can not include linux/pagemap.h because of the following circular dependency: asm-sparc/pgtable include linux/swap.h linux/swap.h include now linux/pagemap.h linux/pagemap.h include linux/mm.h linux/mm.h include asm/pgtable.h It needs to have the swp_entry_t type fully visible in pgtable.h, we can't work around this using macros. Signed-off-by: Olaf Hering Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 239f520cc49e..bfe3e763ccf2 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -255,6 +254,8 @@ static inline void put_swap_token(struct mm_struct *mm) #define si_swapinfo(val) \ do { (val)->freeswap = (val)->totalswap = 0; } while (0) +/* only sparc can not include linux/pagemap.h in this file + * so leave page_cache_release and release_pages undeclared... */ #define free_page_and_swap_cache(page) \ page_cache_release(page) #define free_pages_and_swap_cache(pages, nr) \ -- cgit v1.2.3 From 68b47139ea94ab6d05e89c654db8daa99e9a232c Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Sun, 7 Aug 2005 09:42:25 -0700 Subject: [PATCH] namespace.c: fix bind mount from foreign namespace I'm resending this patch, because I still believe it's the correct fix. Tested before/after applying the patch with a test application available from: http://www.inf.bme.hu/~mszeredi/nstest.c Bind mount from a foreign namespace results in an un-removable mount. The reason is that mnt->mnt_namespace is copied from the old mount in clone_mnt(). Because of this check_mnt() in sys_umount() will fail. The solution is to set mnt->mnt_namespace to current->namespace in clone_mnt(). clone_mnt() is either called from do_loopback() or copy_tree(). copy_tree() is called from do_loopback() or copy_namespace(). When called (directly or indirectly) from do_loopback(), always current->namspace is being modified: check_mnt(nd->mnt). So setting mnt->mnt_namespace to current->namspace is the right thing to do. When called from copy_namespace(), the setting of mnt_namespace is irrelevant, since mnt_namespace is reset later in that function for all copied mounts. Jamie said: This patch is correct. The old code was buggy for more fundamental and serious reason: it broke the invariant that a tree of vfsmnts all have the same value of mnt_namespace (and the same for the mnt_list list). Signed-off-by: Miklos Szeredi Acked-by: Jamie Lokier Cc: Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index 587eb0d707ee..79bd8a46e1e7 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -160,7 +160,7 @@ clone_mnt(struct vfsmount *old, struct dentry *root) mnt->mnt_root = dget(root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - mnt->mnt_namespace = old->mnt_namespace; + mnt->mnt_namespace = current->namespace; /* stick the duplicate mount on the same expiry list * as the original if that was on one */ -- cgit v1.2.3 From 8b0ed2fbdbea3f0d34404f1cbfdf02c4a673ca56 Mon Sep 17 00:00:00 2001 From: Aristeu Sergio Rozanski Filho Date: Sun, 7 Aug 2005 09:42:28 -0700 Subject: [PATCH] ppc32: 8xx: convert fec driver to use work_struct 8xx: convert fec driver to use work_struct Signed-off-by: Aristeu Sergio Rozanski Filho Signed-off-by: Marcelo Tosatti Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/8xx_io/fec.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c index 0730392dcc20..33ff2976ce25 100644 --- a/arch/ppc/8xx_io/fec.c +++ b/arch/ppc/8xx_io/fec.c @@ -173,7 +173,7 @@ struct fec_enet_private { uint phy_status; uint phy_speed; phy_info_t *phy; - struct tq_struct phy_task; + struct work_struct phy_task; uint sequence_done; @@ -1263,8 +1263,9 @@ static void mii_display_status(struct net_device *dev) printk(".\n"); } -static void mii_display_config(struct net_device *dev) +static void mii_display_config(void *priv) { + struct net_device *dev = (struct net_device *)priv; struct fec_enet_private *fep = dev->priv; volatile uint *s = &(fep->phy_status); @@ -1294,8 +1295,9 @@ static void mii_display_config(struct net_device *dev) fep->sequence_done = 1; } -static void mii_relink(struct net_device *dev) +static void mii_relink(void *priv) { + struct net_device *dev = (struct net_device *)priv; struct fec_enet_private *fep = dev->priv; int duplex; @@ -1323,18 +1325,16 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep = dev->priv; - fep->phy_task.routine = (void *)mii_relink; - fep->phy_task.data = dev; - schedule_task(&fep->phy_task); + INIT_WORK(&fep->phy_task, mii_relink, (void *)dev); + schedule_work(&fep->phy_task); } static void mii_queue_config(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep = dev->priv; - fep->phy_task.routine = (void *)mii_display_config; - fep->phy_task.data = dev; - schedule_task(&fep->phy_task); + INIT_WORK(&fep->phy_task, mii_display_config, (void *)dev); + schedule_work(&fep->phy_task); } -- cgit v1.2.3 From fc007ddd609ccfce1cd392e65eed05aba8db32ce Mon Sep 17 00:00:00 2001 From: Aristeu Sergio Rozanski Filho Date: Sun, 7 Aug 2005 09:42:33 -0700 Subject: [PATCH] ppc32: 8xx: using dma_alloc_coherent() instead consistent_alloc() 8xx: using dma_alloc_coherent() instead consistent_alloc() Signed-off-by: Aristeu Sergio Rozanski Filho Signed-off-by: Marcelo Tosatti Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/8xx_io/fec.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c index 33ff2976ce25..8a9a76c1467d 100644 --- a/arch/ppc/8xx_io/fec.c +++ b/arch/ppc/8xx_io/fec.c @@ -1575,7 +1575,7 @@ static int __init fec_enet_init(void) struct fec_enet_private *fep; int i, j, k, err; unsigned char *eap, *iap, *ba; - unsigned long mem_addr; + dma_addr_t mem_addr; volatile cbd_t *bdp; cbd_t *cbd_base; volatile immap_t *immap; @@ -1640,7 +1640,8 @@ static int __init fec_enet_init(void) printk("FEC initialization failed.\n"); return 1; } - cbd_base = (cbd_t *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr); + cbd_base = (cbd_t *)dma_alloc_coherent(dev->class_dev.dev, PAGE_SIZE, + &mem_addr, GFP_KERNEL); /* Set receive and transmit descriptor base. */ @@ -1657,7 +1658,10 @@ static int __init fec_enet_init(void) /* Allocate a page. */ - ba = (unsigned char *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr); + ba = (unsigned char *)dma_alloc_coherent(dev->class_dev.dev, + PAGE_SIZE, + &mem_addr, + GFP_KERNEL); /* BUG: no check for failure */ /* Initialize the BD for every fragment in the page. -- cgit v1.2.3 From fbccb3d7f56654dbc407f757c884f22d26264e42 Mon Sep 17 00:00:00 2001 From: Aristeu Sergio Rozanski Filho Date: Sun, 7 Aug 2005 09:42:36 -0700 Subject: [PATCH] ppc32: 8xx: fec: fix interrupt handler prototypes 8xx: fec: fix interrupt handler prototypes Signed-off-by: Aristeu Sergio Rozanski Filho Signed-off-by: Marcelo Tosatti Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/8xx_io/fec.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c index 8a9a76c1467d..62f68d6181c6 100644 --- a/arch/ppc/8xx_io/fec.c +++ b/arch/ppc/8xx_io/fec.c @@ -199,7 +199,8 @@ static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); #ifdef CONFIG_USE_MDIO static void fec_enet_mii(struct net_device *dev); #endif /* CONFIG_USE_MDIO */ -static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs); +static irqreturn_t fec_enet_interrupt(int irq, void * dev_id, + struct pt_regs * regs); #ifdef CONFIG_FEC_PACKETHOOK static void fec_enet_tx(struct net_device *dev, __u32 regval); static void fec_enet_rx(struct net_device *dev, __u32 regval); @@ -471,7 +472,7 @@ fec_timeout(struct net_device *dev) /* The interrupt handler. * This is called from the MPC core interrupt. */ -static void +static irqreturn_t fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs) { struct net_device *dev = dev_id; @@ -525,6 +526,7 @@ printk("%s[%d] %s: unexpected FEC_ENET_MII event\n", __FILE__,__LINE__,__FUNCTIO } } + return IRQ_RETVAL(IRQ_HANDLED); } @@ -1403,11 +1405,11 @@ mii_discover_phy(uint mii_reg, struct net_device *dev) /* This interrupt occurs when the PHY detects a link change. */ -static void +static #ifdef CONFIG_RPXCLASSIC -mii_link_interrupt(void *dev_id) +void mii_link_interrupt(void *dev_id) #else -mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs) +irqreturn_t mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs) #endif { #ifdef CONFIG_USE_MDIO @@ -1440,6 +1442,9 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs) printk("%s[%d] %s: unexpected Link interrupt\n", __FILE__,__LINE__,__FUNCTION__); #endif /* CONFIG_USE_MDIO */ +#ifndef CONFIG_RPXCLASSIC + return IRQ_RETVAL(IRQ_HANDLED); +#endif /* CONFIG_RPXCLASSIC */ } static int -- cgit v1.2.3 From b7f08aabb1cdc0d714d312e2ad2feefb498daf77 Mon Sep 17 00:00:00 2001 From: Aristeu Sergio Rozanski Filho Date: Sun, 7 Aug 2005 09:42:40 -0700 Subject: [PATCH] ppc32: 8xx fix CPM ethernet description 8xx: fix CPM Ethernet description Signed-off-by: Marcelo Tosatti Signed-off-by: Aristeu Sergio Rozanski Filho Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/8xx_io/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc/8xx_io/Kconfig b/arch/ppc/8xx_io/Kconfig index 9e2227ec3b34..35925b8b491c 100644 --- a/arch/ppc/8xx_io/Kconfig +++ b/arch/ppc/8xx_io/Kconfig @@ -71,7 +71,7 @@ config ENET_BIG_BUFFERS bool "Use Big CPM Ethernet Buffers" depends on NET_ETHERNET help - Allocate large buffers for MPC8xx Etherenet. Increases throughput + Allocate large buffers for MPC8xx Ethernet. Increases throughput and decreases the likelihood of dropped packets, but costs memory. config HTDMSOUND -- cgit v1.2.3 From ff085c1cc26532294e91f69c1747994fa2283369 Mon Sep 17 00:00:00 2001 From: Aristeu Sergio Rozanski Filho Date: Sun, 7 Aug 2005 09:42:43 -0700 Subject: [PATCH] ppc32: 8xx restrict ENET_BIG_BUFFERS option 8xx: restrict ENET_BIG_BUFFERS option to drivers which actually use it Signed-off-by: Aristeu Sergio Rozanski Filho Signed-off-by: Marcelo Tosatti Signed-off-by: Linus Torvalds --- arch/ppc/8xx_io/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc/8xx_io/Kconfig b/arch/ppc/8xx_io/Kconfig index 35925b8b491c..57dacf978532 100644 --- a/arch/ppc/8xx_io/Kconfig +++ b/arch/ppc/8xx_io/Kconfig @@ -69,7 +69,7 @@ config FEC_QS6612 config ENET_BIG_BUFFERS bool "Use Big CPM Ethernet Buffers" - depends on NET_ETHERNET + depends on SCC_ENET || FEC_ENET help Allocate large buffers for MPC8xx Ethernet. Increases throughput and decreases the likelihood of dropped packets, but costs memory. -- cgit v1.2.3 From 204085c52aa9975a90a894cb385360a141f1e4a3 Mon Sep 17 00:00:00 2001 From: Aristeu Sergio Rozanski Filho Date: Sun, 7 Aug 2005 09:42:46 -0700 Subject: [PATCH] ppc32: 8xx kill unused variable in commproc 8xx: commproc.c: kill unused variable Signed-off-by: Aristeu Sergio Rozanski Filho Signed-off-by: Marcelo Tosatti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/8xx_io/commproc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c index 0cc2e7a9cb11..67194c18dd5c 100644 --- a/arch/ppc/8xx_io/commproc.c +++ b/arch/ppc/8xx_io/commproc.c @@ -384,8 +384,6 @@ static rh_info_t cpm_dpmem_info; void m8xx_cpm_dpinit(void) { - cpm8xx_t *cp = &((immap_t *)IMAP_ADDR)->im_cpm; - spin_lock_init(&cpm_dpmem_lock); /* Initialize the info header */ -- cgit v1.2.3 From 079da354db3473b56eb938ca53a2cb0804ea9c8c Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Sun, 7 Aug 2005 09:42:47 -0700 Subject: [PATCH] ppc32: 8xx commproc avoid direct pte manipulation, use dma coherent API instead Touching the pte directly causes the 8Mbyte TLB entry to be invalidated. This has been fixed in v2.4 for ages. Signed-off-by: Marcelo Tosatti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/8xx_io/commproc.c | 18 +----------------- arch/ppc/syslib/m8xx_setup.c | 8 ++------ 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c index 67194c18dd5c..11726e2a4ec8 100644 --- a/arch/ppc/8xx_io/commproc.c +++ b/arch/ppc/8xx_io/commproc.c @@ -39,8 +39,6 @@ #include #include -extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep); - static void m8xx_cpm_dpinit(void); static uint host_buffer; /* One page of host buffer */ static uint host_end; /* end + 1 */ @@ -108,14 +106,11 @@ struct hw_interrupt_type cpm_pic = { .end = cpm_eoi, }; -extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); - void -m8xx_cpm_reset(uint bootpage) +m8xx_cpm_reset(void) { volatile immap_t *imp; volatile cpm8xx_t *commproc; - pte_t *pte; imp = (immap_t *)IMAP_ADDR; commproc = (cpm8xx_t *)&imp->im_cpm; @@ -143,17 +138,6 @@ m8xx_cpm_reset(uint bootpage) /* Reclaim the DP memory for our use. */ m8xx_cpm_dpinit(); - /* get the PTE for the bootpage */ - if (!get_pteptr(&init_mm, bootpage, &pte)) - panic("get_pteptr failed\n"); - - /* and make it uncachable */ - pte_val(*pte) |= _PAGE_NO_CACHE; - _tlbie(bootpage); - - host_buffer = bootpage; - host_end = host_buffer + PAGE_SIZE; - /* Tell everyone where the comm processor resides. */ cpmp = (cpm8xx_t *)commproc; diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index c1db2ab1d154..55a381af4e37 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c @@ -57,7 +57,7 @@ unsigned char __res[sizeof(bd_t)]; extern void m8xx_ide_init(void); extern unsigned long find_available_memory(void); -extern void m8xx_cpm_reset(uint cpm_page); +extern void m8xx_cpm_reset(); extern void m8xx_wdt_handler_install(bd_t *bp); extern void rpxfb_alloc_pages(void); extern void cpm_interrupt_init(void); @@ -70,13 +70,9 @@ board_init(void) void __init m8xx_setup_arch(void) { - int cpm_page; - - cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE); - /* Reset the Communication Processor Module. */ - m8xx_cpm_reset(cpm_page); + m8xx_cpm_reset(); #ifdef CONFIG_FB_RPX rpxfb_alloc_pages(); -- cgit v1.2.3 From 4b0271eb9da5170ab5cadf2edf97c84712c82550 Mon Sep 17 00:00:00 2001 From: Ravikiran G Thirumalai Date: Sun, 7 Aug 2005 09:42:50 -0700 Subject: [PATCH] Move the fix to align node_end_pfns to a proper location Move the fix to align node_end_pfns to a proper location. The earlier fix made the node_remap_start_vaddr to get misaligned causing remap_numa_kva to barf again :-/ Signed-off-by: Ravikiran Thirumalai Signed-off-by: Shai Fultheim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/discontig.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c index c369a8bf7cbe..6711ce3f6916 100644 --- a/arch/i386/mm/discontig.c +++ b/arch/i386/mm/discontig.c @@ -243,14 +243,6 @@ static unsigned long calculate_numa_remap_pages(void) /* now the roundup is correct, convert to PAGE_SIZE pages */ size = size * PTRS_PER_PTE; - if (node_end_pfn[nid] & (PTRS_PER_PTE-1)) { - /* - * Adjust size if node_end_pfn is not on a proper - * pmd boundary. remap_numa_kva will barf otherwise. - */ - size += node_end_pfn[nid] & (PTRS_PER_PTE-1); - } - /* * Validate the region we are allocating only contains valid * pages. @@ -270,6 +262,17 @@ static unsigned long calculate_numa_remap_pages(void) reserve_pages += size; printk("Shrinking node %d from %ld pages to %ld pages\n", nid, node_end_pfn[nid], node_end_pfn[nid] - size); + + if (node_end_pfn[nid] & (PTRS_PER_PTE-1)) { + /* + * Align node_end_pfn[] and node_remap_start_pfn[] to + * pmd boundary. remap_numa_kva will barf otherwise. + */ + printk("Shrinking node %d further by %ld pages for proper alignment\n", + nid, node_end_pfn[nid] & (PTRS_PER_PTE-1)); + size += node_end_pfn[nid] & (PTRS_PER_PTE-1); + } + node_end_pfn[nid] -= size; node_remap_start_pfn[nid] = node_end_pfn[nid]; } -- cgit v1.2.3 From cfc646fa848dfa124fe4d6e0e44ef6940f7f9e6d Mon Sep 17 00:00:00 2001 From: Dominik Hackl Date: Sun, 7 Aug 2005 09:42:53 -0700 Subject: [PATCH] crc32.c typo fix This patch fixes a typo in lib/crc32.c which results in incorrect debug output. Signed-off-by: Dominik Hackl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/crc32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/crc32.c b/lib/crc32.c index 58b222783f9c..065198f98b3f 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -473,7 +473,7 @@ static u32 test_step(u32 init, unsigned char *buf, size_t len) init = bitreverse(init); crc2 = bitreverse(crc1); if (crc1 != bitreverse(crc2)) - printf("\nBit reversal fail: 0x%08x -> %0x08x -> 0x%08x\n", + printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n", crc1, crc2, bitreverse(crc2)); crc1 = crc32_le(init, buf, len); if (crc1 != crc2) -- cgit v1.2.3 From 6fc32179de9e14c542e0b1760e412bc670611c53 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 7 Aug 2005 11:18:56 -0700 Subject: Linux 2.6.13-rc6 Last (?) -rc, partly brought on by the aic7xxx performance fixes (ie get them tested in an -rc release before the real 2.6.13). --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0196b209bb19..2c1486159d8d 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 13 -EXTRAVERSION =-rc5 +EXTRAVERSION =-rc6 NAME=Woozy Numbat # *DOCUMENTATION* -- cgit v1.2.3 From 9c472dd9197429a37691e91c938660a062bf20b0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 8 Aug 2005 11:51:38 -0500 Subject: [SCSI] Bug 4940 Repeatable Kernel Panic on Adaptec 2015S I20 device on bootup From: "Salyzyn, Mark" Prevent driver from loading if another driver (i2o) has already claimed the resources associated with the card. Discussion associated with this bug can be referenced at http://bugzilla.kernel.org/show_bug.cgi?id=4940 where it was agreed to use pci_request_regions in both the dpt_i2o and the i2o driver to prevent both drivers loading on the same adapter(s). Signed-off-by: Mark Salyzyn Rejections fixed up and Signed-off-by: James Bottomley --- drivers/scsi/dpt_i2o.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index e2370529c632..bc7b84c95db6 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -907,9 +907,13 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev raptorFlag = TRUE; } - + if (pci_request_regions(pDev)) { + PERROR("dpti: adpt_config_hba: pci request region failed\n"); + return -EINVAL; + } base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); if (!base_addr_virt) { + pci_release_regions(pDev); PERROR("dpti: adpt_config_hba: io remap failed\n"); return -EINVAL; } @@ -919,6 +923,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev if (!msg_addr_virt) { PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); iounmap(base_addr_virt); + pci_release_regions(pDev); return -EINVAL; } } else { @@ -932,6 +937,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev iounmap(msg_addr_virt); } iounmap(base_addr_virt); + pci_release_regions(pDev); return -ENOMEM; } memset(pHba, 0, sizeof(adpt_hba)); @@ -1027,6 +1033,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) up(&adpt_configuration_lock); iounmap(pHba->base_addr_virt); + pci_release_regions(pHba->pDev); if(pHba->msg_addr_virt != pHba->base_addr_virt){ iounmap(pHba->msg_addr_virt); } -- cgit v1.2.3 From 2c875bbda9303b359af94f671d25639840ce2a59 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Aug 2005 14:12:42 +1000 Subject: [PATCH] ppc64: add default config for BPA This adds a bpa_defconfig file and make target. The config settings are made for the current version of the Cell Processor Based Blade, so there are not too many drivers enabled. A few more drivers might get added in the future though. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- arch/ppc64/configs/bpa_defconfig | 987 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 987 insertions(+) create mode 100644 arch/ppc64/configs/bpa_defconfig diff --git a/arch/ppc64/configs/bpa_defconfig b/arch/ppc64/configs/bpa_defconfig new file mode 100644 index 000000000000..46c5da41c3ae --- /dev/null +++ b/arch/ppc64/configs/bpa_defconfig @@ -0,0 +1,987 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.13-rc6 +# Mon Aug 8 14:12:19 2005 +# +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_EARLY_PRINTK=y +CONFIG_COMPAT=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_FORCE_MAX_ZONEORDER=13 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +# CONFIG_CPUSETS is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set +CONFIG_STOP_MACHINE=y +CONFIG_SYSVIPC_COMPAT=y + +# +# Platform support +# +# CONFIG_PPC_ISERIES is not set +CONFIG_PPC_MULTIPLATFORM=y +# CONFIG_PPC_PSERIES is not set +CONFIG_PPC_BPA=y +# CONFIG_PPC_PMAC is not set +# CONFIG_PPC_MAPLE is not set +CONFIG_PPC=y +CONFIG_PPC64=y +CONFIG_PPC_OF=y +CONFIG_BPA_IIC=y +CONFIG_ALTIVEC=y +CONFIG_KEXEC=y +# CONFIG_U3_DART is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_POWER4_ONLY is not set +# CONFIG_IOMMU_VMERGE is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_NUMA is not set +CONFIG_SCHED_SMT=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_GENERIC_HARDIRQS=y +CONFIG_PPC_RTAS=y +CONFIG_RTAS_PROC=y +CONFIG_RTAS_FLASH=y +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# General setup +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=y +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_IP_TCPDIAG=y +CONFIG_IP_TCPDIAG_IPV6=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=y +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +CONFIG_IP_NF_CT_PROTO_SCTP=y +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +CONFIG_IP_NF_MATCH_SCTP=m +CONFIG_IP_NF_MATCH_COMMENT=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_TARGET_NOTRACK=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +# CONFIG_IP6_NF_QUEUE is not set +# CONFIG_IP6_NF_IPTABLES is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=m +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +CONFIG_SKGE=m +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_MV643XX_ETH is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_WATCHDOG_RTAS=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_ISA is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set +# CONFIG_I2C_SENSOR is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y + +# +# XFS support +# +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +# CONFIG_TMPFS_SECURITY is not set +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_LOG_BUF_SHIFT=15 +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_KPROBES is not set +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUGGER=y +# CONFIG_XMON is not set +# CONFIG_PPCDBG is not set +CONFIG_IRQSTACKS=y + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m -- cgit v1.2.3 From 0f0767c67a497173294bdf6725a3d85f7f29e397 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 8 Aug 2005 14:16:43 +1000 Subject: [PATCH] ppc64: update defconfigs Update the default/example configs for ppc64. Pretty boring... Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds --- arch/ppc64/configs/g5_defconfig | 12 +++++------- arch/ppc64/configs/iSeries_defconfig | 14 +++++++------- arch/ppc64/configs/maple_defconfig | 9 ++++----- arch/ppc64/configs/pSeries_defconfig | 14 +++++++------- arch/ppc64/defconfig | 16 +++++++--------- 5 files changed, 30 insertions(+), 35 deletions(-) diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig index 9e0abe8392fc..ab567741e80e 100644 --- a/arch/ppc64/configs/g5_defconfig +++ b/arch/ppc64/configs/g5_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc3 -# Wed Jul 13 14:40:34 2005 +# Linux kernel version: 2.6.13-rc6 +# Mon Aug 8 14:16:59 2005 # CONFIG_64BIT=y CONFIG_MMU=y @@ -267,8 +267,6 @@ CONFIG_NET_CLS_ROUTE=y # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -468,6 +466,7 @@ CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA2300 is not set # CONFIG_SCSI_QLA2322 is not set # CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA24XX is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -539,11 +538,9 @@ CONFIG_IEEE1394_RAWIO=y # # Macintosh device drivers # -CONFIG_ADB=y CONFIG_ADB_PMU=y CONFIG_PMAC_SMU=y # CONFIG_PMAC_BACKLIGHT is not set -# CONFIG_INPUT_ADBHID is not set CONFIG_THERM_PM72=y # @@ -631,6 +628,8 @@ CONFIG_PPPOE=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -718,7 +717,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig index dbd54d188c2b..394ba18b58c7 100644 --- a/arch/ppc64/configs/iSeries_defconfig +++ b/arch/ppc64/configs/iSeries_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc3 -# Wed Jul 13 14:43:39 2005 +# Linux kernel version: 2.6.13-rc6 +# Mon Aug 8 14:17:02 2005 # CONFIG_64BIT=y CONFIG_MMU=y @@ -257,10 +257,6 @@ CONFIG_NET_CLS_ROUTE=y # Network testing # # CONFIG_NET_PKTGEN is not set -CONFIG_NETPOLL=y -CONFIG_NETPOLL_RX=y -CONFIG_NETPOLL_TRAP=y -CONFIG_NET_POLL_CONTROLLER=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -388,6 +384,7 @@ CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA2300 is not set # CONFIG_SCSI_QLA2322 is not set # CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA24XX is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -537,6 +534,10 @@ CONFIG_PPPOE=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=y +CONFIG_NETPOLL=y +CONFIG_NETPOLL_RX=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y # # ISDN subsystem @@ -610,7 +611,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set diff --git a/arch/ppc64/configs/maple_defconfig b/arch/ppc64/configs/maple_defconfig index cda8e8cb6d1d..2033fe663dbe 100644 --- a/arch/ppc64/configs/maple_defconfig +++ b/arch/ppc64/configs/maple_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc3 -# Wed Jul 13 14:46:18 2005 +# Linux kernel version: 2.6.13-rc6 +# Mon Aug 8 14:17:04 2005 # CONFIG_64BIT=y CONFIG_MMU=y @@ -193,8 +193,6 @@ CONFIG_TCP_CONG_BIC=y # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -433,6 +431,8 @@ CONFIG_E1000=y # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -512,7 +512,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig index 5112edf18181..297fd5229487 100644 --- a/arch/ppc64/configs/pSeries_defconfig +++ b/arch/ppc64/configs/pSeries_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc3 -# Wed Jul 13 14:47:54 2005 +# Linux kernel version: 2.6.13-rc6 +# Mon Aug 8 14:17:07 2005 # CONFIG_64BIT=y CONFIG_MMU=y @@ -287,10 +287,6 @@ CONFIG_NET_CLS_ROUTE=y # Network testing # # CONFIG_NET_PKTGEN is not set -CONFIG_NETPOLL=y -CONFIG_NETPOLL_RX=y -CONFIG_NETPOLL_TRAP=y -CONFIG_NET_POLL_CONTROLLER=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -488,6 +484,7 @@ CONFIG_SCSI_QLA22XX=m CONFIG_SCSI_QLA2300=m CONFIG_SCSI_QLA2322=m CONFIG_SCSI_QLA6312=m +CONFIG_SCSI_QLA24XX=m CONFIG_SCSI_LPFC=m # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -645,6 +642,10 @@ CONFIG_PPPOE=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=y +CONFIG_NETPOLL=y +CONFIG_NETPOLL_RX=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y # # ISDN subsystem @@ -746,7 +747,6 @@ CONFIG_HVCS=m # # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig index fbf1f427ad35..c361e7727b7a 100644 --- a/arch/ppc64/defconfig +++ b/arch/ppc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc3 -# Wed Jul 13 14:37:07 2005 +# Linux kernel version: 2.6.13-rc6 +# Mon Aug 8 14:16:54 2005 # CONFIG_64BIT=y CONFIG_MMU=y @@ -289,10 +289,6 @@ CONFIG_NET_CLS_ROUTE=y # Network testing # # CONFIG_NET_PKTGEN is not set -CONFIG_NETPOLL=y -CONFIG_NETPOLL_RX=y -CONFIG_NETPOLL_TRAP=y -CONFIG_NET_POLL_CONTROLLER=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -506,6 +502,7 @@ CONFIG_SCSI_QLA22XX=m CONFIG_SCSI_QLA2300=m CONFIG_SCSI_QLA2322=m CONFIG_SCSI_QLA6312=m +CONFIG_SCSI_QLA24XX=m CONFIG_SCSI_LPFC=m # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -579,11 +576,9 @@ CONFIG_IEEE1394_AMDTP=m # # Macintosh device drivers # -CONFIG_ADB=y CONFIG_ADB_PMU=y CONFIG_PMAC_SMU=y # CONFIG_PMAC_BACKLIGHT is not set -# CONFIG_INPUT_ADBHID is not set CONFIG_THERM_PM72=y # @@ -694,6 +689,10 @@ CONFIG_PPPOE=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=y +CONFIG_NETPOLL=y +CONFIG_NETPOLL_RX=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y # # ISDN subsystem @@ -797,7 +796,6 @@ CONFIG_HVCS=m # # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -- cgit v1.2.3 From db6778db7eb1d974e1ae0da326530f09c13585ac Mon Sep 17 00:00:00 2001 From: Antonino Daplas Date: Mon, 8 Aug 2005 14:22:43 +0800 Subject: [PATCH] nvidiafb: Fix initial display corruption on certain laptops Reported by:Vincent Fortier (Bugzilla Bug 4768) "At boot time the screen appears moved to the mid right portion of the actual video pannel making the end of the line appears at the left edge... It simply looks like moved half way to the right" His particular hardware has a display with an unusual dimension (1920x1200) but unfortunately has no EDID block. None of the entries in the global mode database is correct for this particular display, and it particularly has difficulty scaling up 640x480 (the default startup mode of nvidiafb) to 1920x1200 which causes the above described problem. 1, Add 1920x1200 to the global mode database. 2. Let nvidiafb base the startup mode from the flatpanel dimensions only if the EDID block is absent, no boot mode parameter is specified by the user, and a flatpanel/LCD display is attached. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds --- drivers/video/modedb.c | 5 +++++ drivers/video/nvidia/nvidia.c | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index fbf659b6dab0..3edc9f49344b 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -246,6 +246,11 @@ static const struct fb_videomode modedb[] = { /* 480x300 @ 72 Hz, 48.0 kHz hsync */ NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0, FB_VMODE_DOUBLE + }, { + /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */ + NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED }, }; diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index b2e6b2407869..52b16850a54e 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -1324,6 +1324,13 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) fb_videomode_to_var(&nvidiafb_default_var, &modedb); nvidiafb_default_var.bits_per_pixel = 8; + } else if (par->fpWidth && par->fpHeight) { + char buf[16]; + + memset(buf, 0, 16); + snprintf(buf, 15, "%dx%d", par->fpWidth, par->fpHeight); + fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb, + specs->modedb_len, &modedb, 8); } if (mode_option) -- cgit v1.2.3 From 6d85f29bb54235d2e184e7155dcd4de908324fe6 Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Mon, 8 Aug 2005 12:55:54 +0400 Subject: [PATCH] VIA VT8235 PCI quirk Like many other southbridges from different manufacturers, VIA VT8235 chip has two non-standard BARs for power management and SMBus registers (see the datasheet at http://www.via.com.tw). This new quirk routine fixes boot problem with 2.6.13-rc2/rc6 kernels on Targa Visionary 811 Athlon64 laptop, as reported by Mikael Pettersson . Signed-off-by: Ivan Kokshaysky Signed-off-by: Linus Torvalds --- drivers/pci/quirks.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8d0968bd527e..a9160ad16581 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -373,6 +373,25 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi ); +/* + * VIA VT8235 ISA Bridge: Two IO regions pointed to by words at + * 0x88 (128 bytes of power management registers) + * 0xd0 (16 bytes of SMB registers) + */ +static void __devinit quirk_vt8235_acpi(struct pci_dev *dev) +{ + u16 pm, smb; + + pci_read_config_word(dev, 0x88, &pm); + pm &= PCI_BASE_ADDRESS_IO_MASK; + quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES); + + pci_read_config_word(dev, 0xd0, &smb); + smb &= PCI_BASE_ADDRESS_IO_MASK; + quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1); +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi); + #ifdef CONFIG_X86_IO_APIC -- cgit v1.2.3 From 48de5beeb0ee821859c79ba5b9462654604d8bf3 Mon Sep 17 00:00:00 2001 From: James Morris Date: Mon, 8 Aug 2005 10:29:08 -0400 Subject: [PATCH] Update contact info for James Morris --- CREDITS | 4 ++-- MAINTAINERS | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CREDITS b/CREDITS index d97e62524ddc..50121d432b62 100644 --- a/CREDITS +++ b/CREDITS @@ -2380,8 +2380,8 @@ E: tmolina@cablespeed.com D: bug fixes, documentation, minor hackery N: James Morris -E: jmorris@redhat.com -W: http://www.intercode.com.au/jmorris/ +E: jmorris@namei.org +W: http://namei.org/ D: Netfilter, Linux Security Modules (LSM), SELinux, IPSec, D: Crypto API, general networking, miscellaneous. S: PO Box 707 diff --git a/MAINTAINERS b/MAINTAINERS index c31ddc4bcdd6..5fd00c075053 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1658,7 +1658,7 @@ M: kuznet@ms2.inr.ac.ru P: Pekka Savola (ipv6) M: pekkas@netcore.fi P: James Morris -M: jmorris@redhat.com +M: jmorris@namei.org P: Hideaki YOSHIFUJI M: yoshfuji@linux-ipv6.org P: Patrick McHardy @@ -2047,7 +2047,7 @@ SELINUX SECURITY MODULE P: Stephen Smalley M: sds@epoch.ncsc.mil P: James Morris -M: jmorris@redhat.com +M: jmorris@namei.org L: linux-kernel@vger.kernel.org (kernel issues) L: selinux@tycho.nsa.gov (general discussion) W: http://www.nsa.gov/selinux -- cgit v1.2.3 From 8b83bc77bf77cc8459cb94e52b08e775104c4c48 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 8 Aug 2005 11:50:55 +0200 Subject: [PATCH] don't try to do any NAT on untracked connections With the introduction of 'rustynat' in 2.6.11, the old tricks of preventing NAT of 'untracked' connections (e.g. NOTRACK target in 'raw' table) are no longer sufficient. The ip_conntrack_untracked.status |= IPS_NAT_DONE_MASK effectively prevents iteration of the 'nat' table, but doesn't prevent nat_packet() to be executed. Since nr_manips is gone in 'rustynat', nat_packet() now implicitly thinks that it has to do NAT on the packet. This patch fixes that problem by explicitly checking for ip_conntrack_untracked in ip_nat_fn(). Signed-off-by: Harald Welte Signed-off-by: Linus Torvalds --- net/ipv4/netfilter/ip_nat_standalone.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index bc59d0d6e89e..91d5ea1dbbc9 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -102,6 +102,10 @@ ip_nat_fn(unsigned int hooknum, return NF_ACCEPT; } + /* Don't try to NAT if this packet is not conntracked */ + if (ct == &ip_conntrack_untracked) + return NF_ACCEPT; + switch (ctinfo) { case IP_CT_RELATED: case IP_CT_RELATED+IP_CT_IS_REPLY: -- cgit v1.2.3 From 66aea23ff84ca81bfaeaf7d63e248b873f5c2616 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 8 Aug 2005 09:22:36 -0700 Subject: [PATCH] s390: use klist in qeth driver From: Martin Schwidesky Convert qeth to the new klist interface and make it compiling again. Signed-off-by: Frank Pavlic Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/s390/net/qeth_main.c | 24 +++++---- drivers/s390/net/qeth_proc.c | 126 +++++++++++++++++++++++-------------------- 2 files changed, 82 insertions(+), 68 deletions(-) diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 8f4d2999af8e..79c74f3a11f5 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -8120,20 +8120,22 @@ static struct notifier_block qeth_ip6_notifier = { #endif static int -qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +__qeth_reboot_event_card(struct device *dev, void *data) { - - struct device *entry; struct qeth_card *card; - down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - list_for_each_entry(entry, &qeth_ccwgroup_driver.driver.devices, - driver_list) { - card = (struct qeth_card *) entry->driver_data; - qeth_clear_ip_list(card, 0, 0); - qeth_qdio_clear_card(card, 0); - } - up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); + card = (struct qeth_card *) dev->driver_data; + qeth_clear_ip_list(card, 0, 0); + qeth_qdio_clear_card(card, 0); + return 0; +} + +static int +qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + + driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL, + __qeth_reboot_event_card); return NOTIFY_DONE; } diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 04719196fd20..f2ccfea8fdb8 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c @@ -27,23 +27,33 @@ const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $"; #define QETH_PROCFILE_NAME "qeth" static struct proc_dir_entry *qeth_procfile; +static int +qeth_procfile_seq_match(struct device *dev, void *data) +{ + return 1; +} + static void * qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct list_head *next_card = NULL; - int i = 0; + struct device *dev; + loff_t nr; down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - if (*offset == 0) + nr = *offset; + if (nr == 0) return SEQ_START_TOKEN; - /* get card at pos *offset */ - list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices) - if (++i == *offset) - return next_card; + dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, + NULL, qeth_procfile_seq_match); - return NULL; + /* get card at pos *offset */ + nr = *offset; + while (nr-- > 1 && dev) + dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, + NULL, qeth_procfile_seq_match); + return (void *) dev; } static void @@ -55,23 +65,21 @@ qeth_procfile_seq_stop(struct seq_file *s, void* it) static void * qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { - struct list_head *next_card = NULL; - struct list_head *current_card; + struct device *prev, *next; if (it == SEQ_START_TOKEN) { - next_card = qeth_ccwgroup_driver.driver.devices.next; - if (next_card->next == next_card) /* list empty */ - return NULL; - (*offset)++; - } else { - current_card = (struct list_head *)it; - if (current_card->next == &qeth_ccwgroup_driver.driver.devices) - return NULL; /* end of list reached */ - next_card = current_card->next; - (*offset)++; + next = driver_find_device(&qeth_ccwgroup_driver.driver, + NULL, NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } - - return next_card; + prev = (struct device *) it; + next = driver_find_device(&qeth_ccwgroup_driver.driver, + prev, NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } static inline const char * @@ -126,7 +134,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it) "-------------- ---- ------ ---------- ---- " "---- ----- -----\n"); } else { - device = list_entry(it, struct device, driver_list); + device = (struct device *) it; card = device->driver_data; seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ", CARD_RDEV_ID(card), @@ -180,17 +188,20 @@ static struct proc_dir_entry *qeth_perf_procfile; static void * qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct list_head *next_card = NULL; - int i = 0; + struct device *dev = NULL; + int nr; down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); /* get card at pos *offset */ - list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){ - if (i == *offset) - return next_card; - i++; - } - return NULL; + dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, + qeth_procfile_seq_match); + + /* get card at pos *offset */ + nr = *offset; + while (nr-- > 1 && dev) + dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, + NULL, qeth_procfile_seq_match); + return (void *) dev; } static void @@ -202,12 +213,14 @@ qeth_perf_procfile_seq_stop(struct seq_file *s, void* it) static void * qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { - struct list_head *current_card = (struct list_head *)it; + struct device *prev, *next; - if (current_card->next == &qeth_ccwgroup_driver.driver.devices) - return NULL; /* end of list reached */ - (*offset)++; - return current_card->next; + prev = (struct device *) it; + next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, + NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } static int @@ -216,7 +229,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) struct device *device; struct qeth_card *card; - device = list_entry(it, struct device, driver_list); + device = (struct device *) it; card = device->driver_data; seq_printf(s, "For card with devnos %s/%s/%s (%s):\n", CARD_RDEV_ID(card), @@ -318,8 +331,8 @@ static struct proc_dir_entry *qeth_ipato_procfile; static void * qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct list_head *next_card = NULL; - int i = 0; + struct device *dev; + loff_t nr; down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); /* TODO: finish this */ @@ -328,13 +341,16 @@ qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) * output driver settings then; * else output setting for respective card */ + + dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, + qeth_procfile_seq_match); + /* get card at pos *offset */ - list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){ - if (i == *offset) - return next_card; - i++; - } - return NULL; + nr = *offset; + while (nr-- > 1 && dev) + dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, + NULL, qeth_procfile_seq_match); + return (void *) dev; } static void @@ -346,18 +362,14 @@ qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it) static void * qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { - struct list_head *current_card = (struct list_head *)it; + struct device *prev, *next; - /* TODO: finish this */ - /* - * maybe SEQ_SATRT_TOKEN can be returned for offset 0 - * output driver settings then; - * else output setting for respective card - */ - if (current_card->next == &qeth_ccwgroup_driver.driver.devices) - return NULL; /* end of list reached */ - (*offset)++; - return current_card->next; + prev = (struct device *) it; + next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, + NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } static int @@ -372,7 +384,7 @@ qeth_ipato_procfile_seq_show(struct seq_file *s, void *it) * output driver settings then; * else output setting for respective card */ - device = list_entry(it, struct device, driver_list); + device = (struct device *) it; card = device->driver_data; return 0; -- cgit v1.2.3 From 1963c907b21e140082d081b1c8f8c2154593c7d7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 8 Aug 2005 09:22:43 -0700 Subject: [PATCH] dvb: lgdt330x frontend: some bug fixes & add lgdt3303 support - Structural changes within lgdt330x driver, framework now supports both chips... tested OK on lgdt3302 and lgdt3303. - Add LG/TUA6034 dvb_pll_desc for ATSC with LG TDVS-H062F & DViCO FusionHDTV5. - Fixed LGDT330X signal strength: For now, always set it to 0. - Corrected LGDT330X boundary condition error in read_snr: dB calculation. Signed-off-by: Mac Michaels Signed-off-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/dvb-pll.c | 16 + drivers/media/dvb/frontends/dvb-pll.h | 1 + drivers/media/dvb/frontends/lgdt330x.c | 549 ++++++++++++++++++++-------- drivers/media/dvb/frontends/lgdt330x.h | 16 +- drivers/media/dvb/frontends/lgdt330x_priv.h | 8 +- drivers/media/video/cx88/cx88-dvb.c | 26 +- 6 files changed, 443 insertions(+), 173 deletions(-) diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 5264310c070e..536c35d969b7 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -225,6 +225,22 @@ struct dvb_pll_desc dvb_pll_tua6034 = { }; EXPORT_SYMBOL(dvb_pll_tua6034); +/* Infineon TUA6034 + * used in LG Innotek TDVS-H062F + */ +struct dvb_pll_desc dvb_pll_tdvs_tua6034 = { + .name = "LG/Infineon TUA6034", + .min = 54000000, + .max = 863000000, + .count = 3, + .entries = { + { 160000000, 44000000, 62500, 0xce, 0x01 }, + { 455000000, 44000000, 62500, 0xce, 0x02 }, + { 999999999, 44000000, 62500, 0xce, 0x04 }, + }, +}; +EXPORT_SYMBOL(dvb_pll_tdvs_tua6034); + /* Philips FMD1216ME * used in Medion Hybrid PCMCIA card and USB Box */ diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index cb794759d89e..205b2d1a8852 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -31,6 +31,7 @@ extern struct dvb_pll_desc dvb_pll_unknown_1; extern struct dvb_pll_desc dvb_pll_tua6010xs; extern struct dvb_pll_desc dvb_pll_env57h1xd5; extern struct dvb_pll_desc dvb_pll_tua6034; +extern struct dvb_pll_desc dvb_pll_tdvs_tua6034; extern struct dvb_pll_desc dvb_pll_tda665x; extern struct dvb_pll_desc dvb_pll_fmd1216me; extern struct dvb_pll_desc dvb_pll_tded4; diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index e94dee50eecd..c48e7c11d708 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -1,11 +1,8 @@ /* - * Support for LGDT3302 & LGDT3303 (DViCO FusionHDTV Gold) - VSB/QAM + * Support for LGDT3302 and LGDT3303 - VSB/QAM * * Copyright (C) 2005 Wilson Michaels * - * Based on code from Kirk Lapray - * Copyright (C) 2005 - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -25,11 +22,13 @@ /* * NOTES ABOUT THIS DRIVER * - * This driver supports DViCO FusionHDTV Gold under Linux. + * This Linux driver supports: + * DViCO FusionHDTV 3 Gold-Q + * DViCO FusionHDTV 3 Gold-T + * DViCO FusionHDTV 5 Gold * * TODO: - * BER and signal strength always return 0. - * Include support for LGDT3303 + * signal strength always returns 0. * */ @@ -41,7 +40,6 @@ #include #include "dvb_frontend.h" -#include "dvb-pll.h" #include "lgdt330x_priv.h" #include "lgdt330x.h" @@ -70,55 +68,37 @@ struct lgdt330x_state u32 current_frequency; }; -static int i2c_writebytes (struct lgdt330x_state* state, - u8 addr, /* demod_address or pll_address */ +static int i2c_write_demod_bytes (struct lgdt330x_state* state, u8 *buf, /* data bytes to send */ int len /* number of bytes to send */ ) { - u8 tmp[] = { buf[0], buf[1] }; struct i2c_msg msg = - { .addr = addr, .flags = 0, .buf = tmp, .len = 2 }; - int err; + { .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 }; int i; + int err; - for (i=1; ii2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err); + printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err); if (err < 0) return err; else return -EREMOTEIO; } - tmp[0]++; - } - return 0; -} - -#if 0 -static int i2c_readbytes (struct lgdt330x_state* state, - u8 addr, /* demod_address or pll_address */ - u8 *buf, /* holds data bytes read */ - int len /* number of bytes to read */ ) -{ - struct i2c_msg msg = - { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len }; - int err; - - if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt330x: %s error (addr %02x, err == %i)\n", __FUNCTION__, addr, err); - return -EREMOTEIO; + msg.buf += 2; } return 0; } -#endif /* * This routine writes the register (reg) to the demod bus * then reads the data returned for (len) bytes. */ -static u8 i2c_selectreadbytes (struct lgdt330x_state* state, +static u8 i2c_read_demod_bytes (struct lgdt330x_state* state, enum I2C_REG reg, u8* buf, int len) { u8 wr [] = { reg }; @@ -139,7 +119,7 @@ static u8 i2c_selectreadbytes (struct lgdt330x_state* state, } /* Software reset */ -int lgdt330x_SwReset(struct lgdt330x_state* state) +static int lgdt3302_SwReset(struct lgdt330x_state* state) { u8 ret; u8 reset[] = { @@ -148,23 +128,83 @@ int lgdt330x_SwReset(struct lgdt330x_state* state) * bits 5-0 are 1 to mask interrupts */ }; - ret = i2c_writebytes(state, - state->config->demod_address, + ret = i2c_write_demod_bytes(state, reset, sizeof(reset)); if (ret == 0) { - /* spec says reset takes 100 ns why wait */ - /* mdelay(100); */ /* keep low for 100mS */ - reset[1] = 0x7f; /* force reset high (inactive) - * and unmask interrupts */ - ret = i2c_writebytes(state, - state->config->demod_address, + + /* force reset high (inactive) and unmask interrupts */ + reset[1] = 0x7f; + ret = i2c_write_demod_bytes(state, reset, sizeof(reset)); } - /* Spec does not indicate a need for this either */ - /*mdelay(5); */ /* wait 5 msec before doing more */ return ret; } +static int lgdt3303_SwReset(struct lgdt330x_state* state) +{ + u8 ret; + u8 reset[] = { + 0x02, + 0x00 /* bit 0 is active low software reset */ + }; + + ret = i2c_write_demod_bytes(state, + reset, sizeof(reset)); + if (ret == 0) { + + /* force reset high (inactive) */ + reset[1] = 0x01; + ret = i2c_write_demod_bytes(state, + reset, sizeof(reset)); + } + return ret; +} + +static int lgdt330x_SwReset(struct lgdt330x_state* state) +{ + switch (state->config->demod_chip) { + case LGDT3302: + return lgdt3302_SwReset(state); + case LGDT3303: + return lgdt3303_SwReset(state); + default: + return -ENODEV; + } +} + +#ifdef MUTE_TDA9887 +static int i2c_write_ntsc_demod (struct lgdt330x_state* state, u8 buf[2]) +{ + struct i2c_msg msg = + { .addr = 0x43, + .flags = 0, + .buf = buf, + .len = 2 }; + int err; + + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { + printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + return 0; +} + +static void fiddle_with_ntsc_if_demod(struct lgdt330x_state* state) +{ + // Experimental code + u8 buf0[] = {0x00, 0x20}; + u8 buf1[] = {0x01, 0x00}; + u8 buf2[] = {0x02, 0x00}; + + i2c_write_ntsc_demod(state, buf0); + i2c_write_ntsc_demod(state, buf1); + i2c_write_ntsc_demod(state, buf2); +} +#endif + static int lgdt330x_init(struct dvb_frontend* fe) { /* Hardware reset is done using gpio[0] of cx23880x chip. @@ -173,22 +213,101 @@ static int lgdt330x_init(struct dvb_frontend* fe) * Maybe there needs to be a callable function in cx88-core or * the caller of this function needs to do it. */ - dprintk("%s entered\n", __FUNCTION__); - return lgdt330x_SwReset((struct lgdt330x_state*) fe->demodulator_priv); + /* + * Array of byte pairs + * to initialize each different chip + */ + static u8 lgdt3302_init_data[] = { + /* Use 50MHz parameter values from spec sheet since xtal is 50 */ + /* Change the value of NCOCTFV[25:0] of carrier + recovery center frequency register */ + VSB_CARRIER_FREQ0, 0x00, + VSB_CARRIER_FREQ1, 0x87, + VSB_CARRIER_FREQ2, 0x8e, + VSB_CARRIER_FREQ3, 0x01, + /* Change the TPCLK pin polarity + data is valid on falling clock */ + DEMUX_CONTROL, 0xfb, + /* Change the value of IFBW[11:0] of + AGC IF/RF loop filter bandwidth register */ + AGC_RF_BANDWIDTH0, 0x40, + AGC_RF_BANDWIDTH1, 0x93, + AGC_RF_BANDWIDTH2, 0x00, + /* Change the value of bit 6, 'nINAGCBY' and + 'NSSEL[1:0] of ACG function control register 2 */ + AGC_FUNC_CTRL2, 0xc6, + /* Change the value of bit 6 'RFFIX' + of AGC function control register 3 */ + AGC_FUNC_CTRL3, 0x40, + /* Set the value of 'INLVTHD' register 0x2a/0x2c + to 0x7fe */ + AGC_DELAY0, 0x07, + AGC_DELAY2, 0xfe, + /* Change the value of IAGCBW[15:8] + of inner AGC loop filter bandwith */ + AGC_LOOP_BANDWIDTH0, 0x08, + AGC_LOOP_BANDWIDTH1, 0x9a + }; + + static u8 lgdt3303_init_data[] = { + 0x4c, 0x14 + }; + + struct lgdt330x_state* state = fe->demodulator_priv; + char *chip_name; + int err; + + switch (state->config->demod_chip) { + case LGDT3302: + chip_name = "LGDT3302"; + err = i2c_write_demod_bytes(state, lgdt3302_init_data, + sizeof(lgdt3302_init_data)); + break; + case LGDT3303: + chip_name = "LGDT3303"; + err = i2c_write_demod_bytes(state, lgdt3303_init_data, + sizeof(lgdt3303_init_data)); +#ifdef MUTE_TDA9887 + fiddle_with_ntsc_if_demod(state); +#endif + break; + default: + chip_name = "undefined"; + printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n"); + err = -ENODEV; + } + dprintk("%s entered as %s\n", __FUNCTION__, chip_name); + if (err < 0) + return err; + return lgdt330x_SwReset(state); } static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber) { - *ber = 0; /* Dummy out for now */ + *ber = 0; /* Not supplied by the demod chips */ return 0; } static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) { - struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + struct lgdt330x_state* state = fe->demodulator_priv; + int err; u8 buf[2]; - i2c_selectreadbytes(state, PACKET_ERR_COUNTER1, buf, sizeof(buf)); + switch (state->config->demod_chip) { + case LGDT3302: + err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1, + buf, sizeof(buf)); + break; + case LGDT3303: + err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1, + buf, sizeof(buf)); + break; + default: + printk(KERN_WARNING + "Only LGDT3302 and LGDT3303 are supported chips.\n"); + err = -ENODEV; + } *ucblocks = (buf[0] << 8) | buf[1]; return 0; @@ -197,123 +316,113 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) static int lgdt330x_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *param) { - struct lgdt330x_state* state = - (struct lgdt330x_state*) fe->demodulator_priv; + /* + * Array of byte pairs + * to initialize 8VSB for lgdt3303 chip 50 MHz IF + */ + static u8 lgdt3303_8vsb_44_data[] = { + 0x04, 0x00, + 0x0d, 0x40, + 0x0e, 0x87, + 0x0f, 0x8e, + 0x10, 0x01, + 0x47, 0x8b }; + + /* + * Array of byte pairs + * to initialize QAM for lgdt3303 chip + */ + static u8 lgdt3303_qam_data[] = { + 0x04, 0x00, + 0x0d, 0x00, + 0x0e, 0x00, + 0x0f, 0x00, + 0x10, 0x00, + 0x51, 0x63, + 0x47, 0x66, + 0x48, 0x66, + 0x4d, 0x1a, + 0x49, 0x08, + 0x4a, 0x9b }; + + struct lgdt330x_state* state = fe->demodulator_priv; - /* Use 50MHz parameter values from spec sheet since xtal is 50 */ static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 }; - static u8 vsb_freq_cfg[] = { VSB_CARRIER_FREQ0, 0x00, 0x87, 0x8e, 0x01 }; - static u8 demux_ctrl_cfg[] = { DEMUX_CONTROL, 0xfb }; - static u8 agc_rf_cfg[] = { AGC_RF_BANDWIDTH0, 0x40, 0x93, 0x00 }; - static u8 agc_ctrl_cfg[] = { AGC_FUNC_CTRL2, 0xc6, 0x40 }; - static u8 agc_delay_cfg[] = { AGC_DELAY0, 0x07, 0x00, 0xfe }; - static u8 agc_loop_cfg[] = { AGC_LOOP_BANDWIDTH0, 0x08, 0x9a }; + int err; /* Change only if we are actually changing the modulation */ if (state->current_modulation != param->u.vsb.modulation) { switch(param->u.vsb.modulation) { case VSB_8: dprintk("%s: VSB_8 MODE\n", __FUNCTION__); - /* Select VSB mode and serial MPEG interface */ - top_ctrl_cfg[1] = 0x07; + /* Select VSB mode */ + top_ctrl_cfg[1] = 0x03; /* Select ANT connector if supported by card */ if (state->config->pll_rf_set) state->config->pll_rf_set(fe, 1); + + if (state->config->demod_chip == LGDT3303) { + err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data, + sizeof(lgdt3303_8vsb_44_data)); + } break; case QAM_64: dprintk("%s: QAM_64 MODE\n", __FUNCTION__); - /* Select QAM_64 mode and serial MPEG interface */ - top_ctrl_cfg[1] = 0x04; + /* Select QAM_64 mode */ + top_ctrl_cfg[1] = 0x00; /* Select CABLE connector if supported by card */ if (state->config->pll_rf_set) state->config->pll_rf_set(fe, 0); + + if (state->config->demod_chip == LGDT3303) { + err = i2c_write_demod_bytes(state, lgdt3303_qam_data, + sizeof(lgdt3303_qam_data)); + } break; case QAM_256: dprintk("%s: QAM_256 MODE\n", __FUNCTION__); - /* Select QAM_256 mode and serial MPEG interface */ - top_ctrl_cfg[1] = 0x05; + /* Select QAM_256 mode */ + top_ctrl_cfg[1] = 0x01; /* Select CABLE connector if supported by card */ if (state->config->pll_rf_set) state->config->pll_rf_set(fe, 0); + + if (state->config->demod_chip == LGDT3303) { + err = i2c_write_demod_bytes(state, lgdt3303_qam_data, + sizeof(lgdt3303_qam_data)); + } break; default: printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation); return -1; } - /* Initializations common to all modes */ + /* + * select serial or parallel MPEG harware interface + * Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303 + * Parallel: 0x00 + */ + top_ctrl_cfg[1] |= state->config->serial_mpeg; /* Select the requested mode */ - i2c_writebytes(state, state->config->demod_address, - top_ctrl_cfg, sizeof(top_ctrl_cfg)); - - /* Change the value of IFBW[11:0] - of AGC IF/RF loop filter bandwidth register */ - i2c_writebytes(state, state->config->demod_address, - agc_rf_cfg, sizeof(agc_rf_cfg)); - - /* Change the value of bit 6, 'nINAGCBY' and - 'NSSEL[1:0] of ACG function control register 2 */ - /* Change the value of bit 6 'RFFIX' - of AGC function control register 3 */ - i2c_writebytes(state, state->config->demod_address, - agc_ctrl_cfg, sizeof(agc_ctrl_cfg)); - - /* Change the TPCLK pin polarity - data is valid on falling clock */ - i2c_writebytes(state, state->config->demod_address, - demux_ctrl_cfg, sizeof(demux_ctrl_cfg)); - - /* Change the value of NCOCTFV[25:0] of carrier - recovery center frequency register */ - i2c_writebytes(state, state->config->demod_address, - vsb_freq_cfg, sizeof(vsb_freq_cfg)); - - /* Set the value of 'INLVTHD' register 0x2a/0x2c to 0x7fe */ - i2c_writebytes(state, state->config->demod_address, - agc_delay_cfg, sizeof(agc_delay_cfg)); - - /* Change the value of IAGCBW[15:8] - of inner AGC loop filter bandwith */ - i2c_writebytes(state, state->config->demod_address, - agc_loop_cfg, sizeof(agc_loop_cfg)); - + i2c_write_demod_bytes(state, top_ctrl_cfg, + sizeof(top_ctrl_cfg)); state->config->set_ts_params(fe, 0); state->current_modulation = param->u.vsb.modulation; } /* Change only if we are actually changing the channel */ if (state->current_frequency != param->frequency) { - u8 buf[5]; - struct i2c_msg msg = { .flags = 0, .buf = &buf[1], .len = 4 }; - int err; - - state->config->pll_set(fe, param, buf); - msg.addr = buf[0]; - - dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x " - "0x%02x 0x%02x\n", __FUNCTION__, - buf[0],buf[1],buf[2],buf[3],buf[4]); - if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } -#if 0 - /* Check the status of the tuner pll */ - i2c_readbytes(state, buf[0], &buf[1], 1); - dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[1]); -#endif - /* Update current frequency */ + /* Tune to the new frequency */ + state->config->pll_set(fe, param); + /* Keep track of the new frequency */ state->current_frequency = param->frequency; } lgdt330x_SwReset(state); @@ -328,21 +437,15 @@ static int lgdt330x_get_frontend(struct dvb_frontend* fe, return 0; } -static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) +static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status) { - struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + struct lgdt330x_state* state = fe->demodulator_priv; u8 buf[3]; *status = 0; /* Reset status result */ - /* - * You must set the Mask bits to 1 in the IRQ_MASK in order - * to see that status bit in the IRQ_STATUS register. - * This is done in SwReset(); - */ - /* AGC status register */ - i2c_selectreadbytes(state, AGC_STATUS, buf, 1); + i2c_read_demod_bytes(state, AGC_STATUS, buf, 1); dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]); if ((buf[0] & 0x0c) == 0x8){ /* Test signal does not exist flag */ @@ -353,16 +456,15 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } + /* + * You must set the Mask bits to 1 in the IRQ_MASK in order + * to see that status bit in the IRQ_STATUS register. + * This is done in SwReset(); + */ /* signal status */ - i2c_selectreadbytes(state, TOP_CONTROL, buf, sizeof(buf)); + i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf)); dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]); -#if 0 - /* Alternative method to check for a signal */ - /* using the SNR good/bad interrupts. */ - if ((buf[2] & 0x30) == 0x10) - *status |= FE_HAS_SIGNAL; -#endif /* sync status */ if ((buf[2] & 0x03) == 0x01) { @@ -376,7 +478,7 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) } /* Carrier Recovery Lock Status Register */ - i2c_selectreadbytes(state, CARRIER_LOCK, buf, 1); + i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1); dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]); switch (state->current_modulation) { case QAM_256: @@ -396,13 +498,75 @@ static int lgdt330x_read_status(struct dvb_frontend* fe, fe_status_t* status) return 0; } +static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status) +{ + struct lgdt330x_state* state = fe->demodulator_priv; + int err; + u8 buf[3]; + + *status = 0; /* Reset status result */ + + /* lgdt3303 AGC status register */ + err = i2c_read_demod_bytes(state, 0x58, buf, 1); + if (err < 0) + return err; + + dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]); + if ((buf[0] & 0x21) == 0x01){ + /* Test input signal does not exist flag */ + /* as well as the AGC lock flag. */ + *status |= FE_HAS_SIGNAL; + } else { + /* Without a signal all other status bits are meaningless */ + return 0; + } + + /* Carrier Recovery Lock Status Register */ + i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1); + dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]); + switch (state->current_modulation) { + case QAM_256: + case QAM_64: + /* Need to undestand why there are 3 lock levels here */ + if ((buf[0] & 0x07) == 0x07) + *status |= FE_HAS_CARRIER; + else + break; + i2c_read_demod_bytes(state, 0x8a, buf, 1); + if ((buf[0] & 0x04) == 0x04) + *status |= FE_HAS_SYNC; + if ((buf[0] & 0x01) == 0x01) + *status |= FE_HAS_LOCK; + if ((buf[0] & 0x08) == 0x08) + *status |= FE_HAS_VITERBI; + break; + case VSB_8: + if ((buf[0] & 0x80) == 0x80) + *status |= FE_HAS_CARRIER; + else + break; + i2c_read_demod_bytes(state, 0x38, buf, 1); + if ((buf[0] & 0x02) == 0x00) + *status |= FE_HAS_SYNC; + if ((buf[0] & 0x01) == 0x01) { + *status |= FE_HAS_LOCK; + *status |= FE_HAS_VITERBI; + } + break; + default: + printk("KERN_WARNING lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__); + } + return 0; +} + static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) { /* not directly available. */ + *strength = 0; return 0; } -static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) +static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) { #ifdef SNR_IN_DB /* @@ -451,7 +615,7 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) 91, 115, 144, 182, 229, 288, 362, 456, 574, 722, 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216, 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151, - 90833, 114351, 143960, 181235, 228161, 0x040000 + 90833, 114351, 143960, 181235, 228161, 0x080000 }; static u8 buf[5];/* read data buffer */ @@ -459,8 +623,8 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) static u32 snr_db; /* index into SNR_EQ[] */ struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; - /* read both equalizer and pase tracker noise data */ - i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf)); + /* read both equalizer and phase tracker noise data */ + i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); if (state->current_modulation == VSB_8) { /* Equalizer Mean-Square Error Register for VSB */ @@ -496,19 +660,20 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; /* read both equalizer and pase tracker noise data */ - i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf)); + i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); if (state->current_modulation == VSB_8) { - /* Equalizer Mean-Square Error Register for VSB */ - noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; - } else { - /* Phase Tracker Mean-Square Error Register for QAM */ + /* Phase Tracker Mean-Square Error Register for VSB */ noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; + } else { + + /* Carrier Recovery Mean-Square Error for QAM */ + i2c_read_demod_bytes(state, 0x1a, buf, 2); + noise = ((buf[0] & 3) << 8) | buf[1]; } /* Small values for noise mean signal is better so invert noise */ - /* Noise is 19 bit value so discard 3 LSB*/ - *snr = ~noise>>3; + *snr = ~noise; #endif dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); @@ -516,6 +681,32 @@ static int lgdt330x_read_snr(struct dvb_frontend* fe, u16* snr) return 0; } +static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) +{ + /* Return the raw noise value */ + static u8 buf[5];/* read data buffer */ + static u32 noise; /* noise value */ + struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; + + if (state->current_modulation == VSB_8) { + + /* Phase Tracker Mean-Square Error Register for VSB */ + noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; + } else { + + /* Carrier Recovery Mean-Square Error for QAM */ + i2c_read_demod_bytes(state, 0x1a, buf, 2); + noise = (buf[0] << 8) | buf[1]; + } + + /* Small values for noise mean signal is better so invert noise */ + *snr = ~noise; + + dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); + + return 0; +} + static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings) { /* I have no idea about this - it may not be needed */ @@ -531,7 +722,8 @@ static void lgdt330x_release(struct dvb_frontend* fe) kfree(state); } -static struct dvb_frontend_ops lgdt330x_ops; +static struct dvb_frontend_ops lgdt3302_ops; +static struct dvb_frontend_ops lgdt3303_ops; struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, struct i2c_adapter* i2c) @@ -548,9 +740,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, /* Setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &lgdt330x_ops, sizeof(struct dvb_frontend_ops)); + switch (config->demod_chip) { + case LGDT3302: + memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops)); + break; + case LGDT3303: + memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops)); + break; + default: + goto error; + } + /* Verify communication with demod chip */ - if (i2c_selectreadbytes(state, 2, buf, 1)) + if (i2c_read_demod_bytes(state, 2, buf, 1)) goto error; state->current_frequency = -1; @@ -568,9 +770,33 @@ error: return NULL; } -static struct dvb_frontend_ops lgdt330x_ops = { +static struct dvb_frontend_ops lgdt3302_ops = { + .info = { + .name= "LG Electronics LGDT3302/LGDT3303 VSB/QAM Frontend", + .type = FE_ATSC, + .frequency_min= 54000000, + .frequency_max= 858000000, + .frequency_stepsize= 62500, + /* Symbol rate is for all VSB modes need to check QAM */ + .symbol_rate_min = 10762000, + .symbol_rate_max = 10762000, + .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB + }, + .init = lgdt330x_init, + .set_frontend = lgdt330x_set_parameters, + .get_frontend = lgdt330x_get_frontend, + .get_tune_settings = lgdt330x_get_tune_settings, + .read_status = lgdt3302_read_status, + .read_ber = lgdt330x_read_ber, + .read_signal_strength = lgdt330x_read_signal_strength, + .read_snr = lgdt3302_read_snr, + .read_ucblocks = lgdt330x_read_ucblocks, + .release = lgdt330x_release, +}; + +static struct dvb_frontend_ops lgdt3303_ops = { .info = { - .name= "LG Electronics lgdt330x VSB/QAM Frontend", + .name= "LG Electronics LGDT3303 VSB/QAM Frontend", .type = FE_ATSC, .frequency_min= 54000000, .frequency_max= 858000000, @@ -584,15 +810,15 @@ static struct dvb_frontend_ops lgdt330x_ops = { .set_frontend = lgdt330x_set_parameters, .get_frontend = lgdt330x_get_frontend, .get_tune_settings = lgdt330x_get_tune_settings, - .read_status = lgdt330x_read_status, + .read_status = lgdt3303_read_status, .read_ber = lgdt330x_read_ber, .read_signal_strength = lgdt330x_read_signal_strength, - .read_snr = lgdt330x_read_snr, + .read_snr = lgdt3303_read_snr, .read_ucblocks = lgdt330x_read_ucblocks, .release = lgdt330x_release, }; -MODULE_DESCRIPTION("lgdt330x [DViCO FusionHDTV 3 Gold] (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); +MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); MODULE_AUTHOR("Wilson Michaels"); MODULE_LICENSE("GPL"); @@ -601,6 +827,5 @@ EXPORT_SYMBOL(lgdt330x_attach); /* * Local variables: * c-basic-offset: 8 - * compile-command: "make DVB=1" * End: */ diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h index 04986f8e7565..e209ba1e47c5 100644 --- a/drivers/media/dvb/frontends/lgdt330x.h +++ b/drivers/media/dvb/frontends/lgdt330x.h @@ -1,5 +1,5 @@ /* - * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM + * Support for LGDT3302 and LGDT3303 - VSB/QAM * * Copyright (C) 2005 Wilson Michaels * @@ -24,14 +24,26 @@ #include +typedef enum lg_chip_t { + UNDEFINED, + LGDT3302, + LGDT3303 +}lg_chip_type; + struct lgdt330x_config { /* The demodulator's i2c address */ u8 demod_address; + /* LG demodulator chip LGDT3302 or LGDT3303 */ + lg_chip_type demod_chip; + + /* MPEG hardware interface - 0:parallel 1:serial */ + int serial_mpeg; + /* PLL interface */ int (*pll_rf_set) (struct dvb_frontend* fe, int index); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pll_address); + int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); /* Need to set device param for start_dma */ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb/frontends/lgdt330x_priv.h index 4143ce8f1a95..59b7c5b9012d 100644 --- a/drivers/media/dvb/frontends/lgdt330x_priv.h +++ b/drivers/media/dvb/frontends/lgdt330x_priv.h @@ -1,5 +1,5 @@ /* - * Support for LGDT3302 & LGDT3303 (DViCO FustionHDTV Gold) - VSB/QAM + * Support for LGDT3302 and LGDT3303 - VSB/QAM * * Copyright (C) 2005 Wilson Michaels * @@ -57,8 +57,10 @@ enum I2C_REG { PH_ERR1= 0x4a, PH_ERR2= 0x4b, DEMUX_CONTROL= 0x66, - PACKET_ERR_COUNTER1= 0x6a, - PACKET_ERR_COUNTER2= 0x6b, + LGDT3302_PACKET_ERR_COUNTER1= 0x6a, + LGDT3302_PACKET_ERR_COUNTER2= 0x6b, + LGDT3303_PACKET_ERR_COUNTER1= 0x8b, + LGDT3303_PACKET_ERR_COUNTER2= 0x8c, }; #endif /* _LGDT330X_PRIV_ */ diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index ef0e9a85c359..78d223257a68 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-dvb.c,v 1.54 2005/07/25 05:13:50 mkrufky Exp $ + * $Id: cx88-dvb.c,v 1.58 2005/08/07 09:24:08 mkrufky Exp $ * * device driver for Conexant 2388x based TV cards * MPEG Transport Stream (DVB) routines @@ -208,14 +208,26 @@ static struct or51132_config pchdtv_hd3000 = { #ifdef HAVE_LGDT330X static int lgdt330x_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params, - u8* pllbuf) + struct dvb_frontend_parameters* params) { struct cx8802_dev *dev= fe->dvb->priv; + u8 buf[4]; + struct i2c_msg msg = + { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; + int err; - pllbuf[0] = dev->core->pll_addr; - dvb_pll_configure(dev->core->pll_desc, &pllbuf[1], - params->frequency, 0); + dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, 0); + dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", + __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); + if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "cx88-dvb: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } return 0; } @@ -244,6 +256,8 @@ static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) static struct lgdt330x_config fusionhdtv_3_gold = { .demod_address = 0x0e, + .demod_chip = LGDT3302, + .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ .pll_set = lgdt330x_pll_set, .set_ts_params = lgdt330x_set_ts_param, }; -- cgit v1.2.3 From 7a91bf7f5c22c8407a9991cbd9ce5bb87caa6b4a Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Mon, 8 Aug 2005 13:52:16 -0400 Subject: [PATCH] fsnotify_name/inoderemove The patch below unhooks fsnotify from vfs_unlink & vfs_rmdir. It introduces two new fsnotify calls, that are hooked in at the dcache level. This not only more closely matches how the VFS layer works, it also avoids the problem with locking and inode lifetimes. The two functions are - fsnotify_nameremove -- called when a directory entry is going away. It notifies the PARENT of the deletion. This is called from d_delete(). - inoderemove -- called when the files inode itself is going away. It notifies the inode that is being deleted. This is called from dentry_iput(). Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- fs/dcache.c | 7 +++++++ fs/namei.c | 3 --- include/linux/fsnotify.h | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 3aa8a7e980d8..a15a2e1f5520 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -101,6 +102,7 @@ static inline void dentry_iput(struct dentry * dentry) list_del_init(&dentry->d_alias); spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); + fsnotify_inoderemove(inode); if (dentry->d_op && dentry->d_op->d_iput) dentry->d_op->d_iput(dentry, inode); else @@ -1165,13 +1167,16 @@ out: void d_delete(struct dentry * dentry) { + int isdir = 0; /* * Are we the only user? */ spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); + isdir = S_ISDIR(dentry->d_inode->i_mode); if (atomic_read(&dentry->d_count) == 1) { dentry_iput(dentry); + fsnotify_nameremove(dentry, isdir); return; } @@ -1180,6 +1185,8 @@ void d_delete(struct dentry * dentry) spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); + + fsnotify_nameremove(dentry, isdir); } static void __d_rehash(struct dentry * entry, struct hlist_head *list) diff --git a/fs/namei.c b/fs/namei.c index 32accb6a672f..57046d98a746 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1802,7 +1802,6 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) up(&dentry->d_inode->i_sem); if (!error) { d_delete(dentry); - fsnotify_rmdir(dentry, dentry->d_inode, dir); } dput(dentry); @@ -1874,9 +1873,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) /* We don't d_delete() NFS sillyrenamed files--they still exist. */ if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { - struct inode *inode = dentry->d_inode; d_delete(dentry); - fsnotify_unlink(dentry, inode, dir); } return error; diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 1cb4935348d8..9db31d251c20 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -67,6 +67,26 @@ static inline void fsnotify_rmdir(struct dentry *dentry, struct inode *inode, inotify_inode_is_dead(inode); } +/* + * fsnotify_nameremove - a filename was removed from a directory + */ +static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) +{ + if (isdir) + isdir = IN_ISDIR; + dnotify_parent(dentry, DN_DELETE); + inotify_dentry_parent_queue_event(dentry, IN_DELETE|isdir, 0, dentry->d_name.name); +} + +/* + * fsnotify_inoderemove - an inode is going away + */ +static inline void fsnotify_inoderemove(struct inode *inode) +{ + inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL); + inotify_inode_is_dead(inode); +} + /* * fsnotify_create - 'name' was linked in */ -- cgit v1.2.3 From 4d479e40e1748a877a24015fc6727b27b77110cd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 8 Aug 2005 13:48:02 -0700 Subject: [NETLINK]: Allocate and kill some netlink numbers. NETLINK_ARPD is unused, allocate it to the Open-iSCSI folks. NETLINK_ROUTE6 and NETLINK_TAPBASE are no longer used, delete them. Signed-off-by: David S. Miller --- include/linux/netlink.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 70c2a9dc4b2b..6552b71bfa73 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -12,15 +12,13 @@ #define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ #define NETLINK_XFRM 6 /* ipsec */ #define NETLINK_SELINUX 7 /* SELinux event notifications */ -#define NETLINK_ARPD 8 +#define NETLINK_ISCSI 8 /* Open-iSCSI */ #define NETLINK_AUDIT 9 /* auditing */ #define NETLINK_FIB_LOOKUP 10 -#define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */ #define NETLINK_NETFILTER 12 /* netfilter subsystem */ #define NETLINK_IP6_FW 13 #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ -#define NETLINK_TAPBASE 16 /* 16 to 31 are ethertap */ #define MAX_LINKS 32 -- cgit v1.2.3 From ca9334523c853e407da7b3a0bd02f54d0fa59414 Mon Sep 17 00:00:00 2001 From: Heikki Orsila Date: Mon, 8 Aug 2005 14:26:52 -0700 Subject: [IPV4]: Debug cleanup Here's a small patch to cleanup NETDEBUG() use in net/ipv4/ for Linux kernel 2.6.13-rc5. Also weird use of indentation is changed in some places. Signed-off-by: Heikki Orsila Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 3 +-- net/ipv4/ip_fragment.c | 8 +++----- net/ipv4/tcp_ipv4.c | 14 ++++++-------- net/ipv4/udp.c | 34 ++++++++++++++++------------------ 4 files changed, 26 insertions(+), 33 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 279f57abfecb..3d78464f64ea 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -936,8 +936,7 @@ int icmp_rcv(struct sk_buff *skb) case CHECKSUM_HW: if (!(u16)csum_fold(skb->csum)) break; - NETDEBUG(if (net_ratelimit()) - printk(KERN_DEBUG "icmp v4 hw csum failure\n")); + LIMIT_NETDEBUG(printk(KERN_DEBUG "icmp v4 hw csum failure\n")); case CHECKSUM_NONE: if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) goto error; diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 7f68e27eb4ea..eb377ae15305 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -377,7 +377,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) return ip_frag_intern(hash, qp); out_nomem: - NETDEBUG(if (net_ratelimit()) printk(KERN_ERR "ip_frag_create: no memory left !\n")); + LIMIT_NETDEBUG(printk(KERN_ERR "ip_frag_create: no memory left !\n")); return NULL; } @@ -625,10 +625,8 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev) return head; out_nomem: - NETDEBUG(if (net_ratelimit()) - printk(KERN_ERR - "IP: queue_glue: no memory for gluing queue %p\n", - qp)); + LIMIT_NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing " + "queue %p\n", qp)); goto out_fail; out_oversize: if (net_ratelimit()) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 62f62bb05c2a..5d91213d34c0 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1494,12 +1494,11 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) * to destinations, already remembered * to the moment of synflood. */ - NETDEBUG(if (net_ratelimit()) \ - printk(KERN_DEBUG "TCP: drop open " - "request from %u.%u." - "%u.%u/%u\n", \ - NIPQUAD(saddr), - ntohs(skb->h.th->source))); + LIMIT_NETDEBUG(printk(KERN_DEBUG "TCP: drop open " + "request from %u.%u." + "%u.%u/%u\n", + NIPQUAD(saddr), + ntohs(skb->h.th->source))); dst_release(dst); goto drop_and_free; } @@ -1627,8 +1626,7 @@ static int tcp_v4_checksum_init(struct sk_buff *skb) skb->nh.iph->daddr, skb->csum)) return 0; - NETDEBUG(if (net_ratelimit()) - printk(KERN_DEBUG "hw tcp v4 csum failed\n")); + LIMIT_NETDEBUG(printk(KERN_DEBUG "hw tcp v4 csum failed\n")); skb->ip_summed = CHECKSUM_NONE; } if (skb->len <= 76) { diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 7c24e64b443f..dc4d07357e3a 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -628,7 +628,7 @@ back_from_confirm: /* ... which is an evident application bug. --ANK */ release_sock(sk); - NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp cork app bug 2\n")); + LIMIT_NETDEBUG(printk(KERN_DEBUG "udp cork app bug 2\n")); err = -EINVAL; goto out; } @@ -693,7 +693,7 @@ static int udp_sendpage(struct sock *sk, struct page *page, int offset, if (unlikely(!up->pending)) { release_sock(sk); - NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp cork app bug 3\n")); + LIMIT_NETDEBUG(printk(KERN_DEBUG "udp cork app bug 3\n")); return -EINVAL; } @@ -1102,7 +1102,7 @@ static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh, skb->ip_summed = CHECKSUM_UNNECESSARY; if (!udp_check(uh, ulen, saddr, daddr, skb->csum)) return 0; - NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp v4 hw csum failure.\n")); + LIMIT_NETDEBUG(printk(KERN_DEBUG "udp v4 hw csum failure.\n")); skb->ip_summed = CHECKSUM_NONE; } if (skb->ip_summed != CHECKSUM_UNNECESSARY) @@ -1181,14 +1181,13 @@ int udp_rcv(struct sk_buff *skb) return(0); short_packet: - NETDEBUG(if (net_ratelimit()) - printk(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n", - NIPQUAD(saddr), - ntohs(uh->source), - ulen, - len, - NIPQUAD(daddr), - ntohs(uh->dest))); + LIMIT_NETDEBUG(printk(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n", + NIPQUAD(saddr), + ntohs(uh->source), + ulen, + len, + NIPQUAD(daddr), + ntohs(uh->dest))); no_header: UDP_INC_STATS_BH(UDP_MIB_INERRORS); kfree_skb(skb); @@ -1199,13 +1198,12 @@ csum_error: * RFC1122: OK. Discards the bad packet silently (as far as * the network is concerned, anyway) as per 4.1.3.4 (MUST). */ - NETDEBUG(if (net_ratelimit()) - printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n", - NIPQUAD(saddr), - ntohs(uh->source), - NIPQUAD(daddr), - ntohs(uh->dest), - ulen)); + LIMIT_NETDEBUG(printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n", + NIPQUAD(saddr), + ntohs(uh->source), + NIPQUAD(daddr), + ntohs(uh->dest), + ulen)); drop: UDP_INC_STATS_BH(UDP_MIB_INERRORS); kfree_skb(skb); -- cgit v1.2.3 From 5c44cd2afad3f7b015542187e147a820600172f1 Mon Sep 17 00:00:00 2001 From: "James.Smart@Emulex.Com" Date: Fri, 10 Jun 2005 22:24:30 -0400 Subject: [SCSI] fix target scanning oops with fc transport class We have some nasty issues with 2.6.12-rc6. Any request to scan on the lpfc or qla2xxx FC adapters will oops. What is happening is the system is defaulting to non-transport registered targets, which inherit the parent of the scan. On this second scan, performed by the attribute, the parent becomes the shost instead of the rport. The slave functions in the 2 FC adapters use starget_to_rport() routines, which incorrectly map the shost as an rport pointer. Additionally, this pointed out other weaknesses: - If the target structure is torn down outside of the transport, we have no method for it to be regenerated at the proper parent. - We have race conditions on the target being allocated by both the midlayer scan (parent=shost) and by the fc transport (parent=rport). Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 16 +++++++++++++++- drivers/scsi/scsi_transport_fc.c | 19 +++++++++++++++++++ include/scsi/scsi_transport.h | 8 ++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 2d3c4ac475f2..48edd67982a5 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -336,9 +336,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, unsigned long flags; const int size = sizeof(struct scsi_target) + shost->transportt->target_size; - struct scsi_target *starget = kmalloc(size, GFP_ATOMIC); + struct scsi_target *starget; struct scsi_target *found_target; + /* + * Obtain the real parent from the transport. The transport + * is allowed to fail (no error) if there is nothing at that + * target id. + */ + if (shost->transportt->target_parent) { + spin_lock_irqsave(shost->host_lock, flags); + parent = shost->transportt->target_parent(shost, channel, id); + spin_unlock_irqrestore(shost->host_lock, flags); + if (!parent) + return NULL; + } + + starget = kmalloc(size, GFP_KERNEL); if (!starget) { printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); return NULL; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 35d1c1e8e345..e6412fce423c 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -1022,6 +1022,23 @@ static int fc_rport_match(struct attribute_container *cont, return &i->rport_attr_cont.ac == cont; } + +/* + * Must be called with shost->host_lock held + */ +static struct device *fc_target_parent(struct Scsi_Host *shost, + int channel, uint id) +{ + struct fc_rport *rport; + + list_for_each_entry(rport, &fc_host_rports(shost), peers) + if ((rport->channel == channel) && + (rport->scsi_target_id == id)) + return &rport->dev; + + return NULL; +} + struct scsi_transport_template * fc_attach_transport(struct fc_function_template *ft) { @@ -1057,6 +1074,8 @@ fc_attach_transport(struct fc_function_template *ft) /* Transport uses the shost workq for scsi scanning */ i->t.create_work_queue = 1; + + i->t.target_parent = fc_target_parent; /* * Setup SCSI Target Attributes. diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index a4f1837a33b1..f6e0bb484c63 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -29,6 +29,14 @@ struct scsi_transport_template { struct transport_container target_attrs; struct transport_container device_attrs; + /* + * If set, call target_parent prior to allocating a scsi_target, + * so we get the appropriate parent for the target. This function + * is required for transports like FC and iSCSI that do not put the + * scsi_target under scsi_host. + */ + struct device *(*target_parent)(struct Scsi_Host *, int, uint); + /* The size of the specific transport attribute structure (a * space of this size will be left at the end of the * scsi_* structure */ -- cgit v1.2.3 From 5e708484d710bcbb44893400f429579f5728cd7d Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 8 Aug 2005 14:49:17 -0700 Subject: [PATCH] ppc32: Fix MPC834x USB memory map offsets The memory mappings for MPC8349 USB MPH and DR modules were reversed. Signed-off-by: Li Yang Signed-off-by: Jiang Bo Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/mpc83xx_devices.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index 75c8e9834ae7..5aaf0e58e1f9 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -191,8 +191,8 @@ struct platform_device ppc_sys_platform_devices[] = { .num_resources = 2, .resource = (struct resource[]) { { - .start = 0x22000, - .end = 0x22fff, + .start = 0x23000, + .end = 0x23fff, .flags = IORESOURCE_MEM, }, { @@ -208,8 +208,8 @@ struct platform_device ppc_sys_platform_devices[] = { .num_resources = 2, .resource = (struct resource[]) { { - .start = 0x23000, - .end = 0x23fff, + .start = 0x22000, + .end = 0x22fff, .flags = IORESOURCE_MEM, }, { -- cgit v1.2.3 From 03c6b749b364fe7b8e47ed8e1ce26baca167c322 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Mon, 8 Aug 2005 14:49:18 -0700 Subject: [PATCH] x86_64: add MODULE_ALIAS for aes modprobe aes does not work on x86_64. i386 has a similar line, this could be the right fix. Would be nice to have in 2.6.13 final. Signed-off-by: Olaf Hering Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/crypto/aes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86_64/crypto/aes.c b/arch/x86_64/crypto/aes.c index 2b5c4010ce38..acfdaa28791e 100644 --- a/arch/x86_64/crypto/aes.c +++ b/arch/x86_64/crypto/aes.c @@ -322,3 +322,4 @@ module_exit(aes_fini); MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("aes"); -- cgit v1.2.3 From fb573856b2d82926b36ed059899d883474a3b9eb Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Mon, 8 Aug 2005 15:25:00 -0700 Subject: [IA64] fix nohalt boot option this changeset broke the "nohalt" kernel boot option. 8df5a500a3e97f7811cdce0f553ca1917ccd4220 default_idle() is looking at new variable can_do_pal_halt. However, that variable did not get cleared upon "nohalt" boot option. Result is that "nohalt" option is ignored until perfmon is exercised. Signed-off-by: Ken Chen Signed-off-by: Tony Luck --- arch/ia64/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 66e840609808..051e050359e4 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -179,7 +179,7 @@ static int can_do_pal_halt = 1; static int __init nohalt_setup(char * str) { - pal_halt = 0; + pal_halt = can_do_pal_halt = 0; return 1; } __setup("nohalt", nohalt_setup); -- cgit v1.2.3 From 138b9dd1fd7b44176af4f3b672060c790b0eaf55 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 8 Aug 2005 16:13:15 -0700 Subject: [PATCH] icn driver fails to unload when no hardware present Fix a null dereference in module unload path. Found by a simple modprobe icn ; rmmod icn Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/icn/icn.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index e0d1b01cc74c..386df71eee74 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1650,7 +1650,7 @@ static void __exit icn_exit(void) { isdn_ctrl cmd; icn_card *card = cards; - icn_card *last; + icn_card *last, *tmpcard; int i; unsigned long flags; @@ -1670,8 +1670,9 @@ static void __exit icn_exit(void) for (i = 0; i < ICN_BCH; i++) icn_free_queue(card, i); } - card = card->next; + tmpcard = card->next; spin_unlock_irqrestore(&card->lock, flags); + card = tmpcard; } card = cards; cards = NULL; -- cgit v1.2.3 From dc836b5b6fcde95f750a4790d8200fabaf563dc9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 8 Aug 2005 18:46:09 -0700 Subject: Revert "[PATCH] PCI: restore BAR values..." Revert commit fec59a711eef002d4ef9eb8de09dd0a26986eb77, which is breaking sparc64 that doesn't have a working pci_update_resource. We'll re-do this after 2.6.13 when we'll do it all properly. --- arch/sparc64/kernel/pci.c | 6 ----- drivers/pci/pci.c | 59 ++++------------------------------------------- drivers/pci/setup-res.c | 2 +- include/linux/pci.h | 3 --- 4 files changed, 5 insertions(+), 65 deletions(-) diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 914e125d3971..bba140d98b1b 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -413,12 +413,6 @@ static int pci_assign_bus_resource(const struct pci_bus *bus, return -EBUSY; } -void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) -{ - /* Not implemented for sparc64... */ - BUG(); -} - int pci_assign_resource(struct pci_dev *pdev, int resource) { struct pcidev_cookie *pcp = pdev->sysdata; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 65ea7d25f691..1b34fc56067e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -221,37 +221,6 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) return best; } -/** - * pci_restore_bars - restore a devices BAR values (e.g. after wake-up) - * @dev: PCI device to have its BARs restored - * - * Restore the BAR values for a given device, so as to make it - * accessible by its driver. - */ -void -pci_restore_bars(struct pci_dev *dev) -{ - int i, numres; - - switch (dev->hdr_type) { - case PCI_HEADER_TYPE_NORMAL: - numres = 6; - break; - case PCI_HEADER_TYPE_BRIDGE: - numres = 2; - break; - case PCI_HEADER_TYPE_CARDBUS: - numres = 1; - break; - default: - /* Should never get here, but just in case... */ - return; - } - - for (i = 0; i < numres; i ++) - pci_update_resource(dev, &dev->resource[i], i); -} - /** * pci_set_power_state - Set the power state of a PCI device * @dev: PCI device to be suspended @@ -270,7 +239,7 @@ int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t); int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { - int pm, need_restore = 0; + int pm; u16 pmcsr, pmc; /* bound the state we're entering */ @@ -309,17 +278,14 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) return -EIO; } - pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); - /* If we're in D3, force entire word to 0. * This doesn't affect PME_Status, disables PME_En, and * sets PowerState to 0. */ - if (dev->current_state >= PCI_D3hot) { - if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) - need_restore = 1; + if (dev->current_state >= PCI_D3hot) pmcsr = 0; - } else { + else { + pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); pmcsr &= ~PCI_PM_CTRL_STATE_MASK; pmcsr |= state; } @@ -342,22 +308,6 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) platform_pci_set_power_state(dev, state); dev->current_state = state; - - /* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT - * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning - * from D3hot to D0 _may_ perform an internal reset, thereby - * going to "D0 Uninitialized" rather than "D0 Initialized". - * For example, at least some versions of the 3c905B and the - * 3c556B exhibit this behaviour. - * - * At least some laptop BIOSen (e.g. the Thinkpad T21) leave - * devices in a D3hot state at boot. Consequently, we need to - * restore at least the BARs so that the device will be - * accessible to its driver. - */ - if (need_restore) - pci_restore_bars(dev); - return 0; } @@ -855,7 +805,6 @@ struct pci_dev *isa_bridge; EXPORT_SYMBOL(isa_bridge); #endif -EXPORT_SYMBOL_GPL(pci_restore_bars); EXPORT_SYMBOL(pci_enable_device_bars); EXPORT_SYMBOL(pci_enable_device); EXPORT_SYMBOL(pci_disable_device); diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 589486704ce3..84eedc965688 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -26,7 +26,7 @@ #include "pci.h" -void +static void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) { struct pci_bus_region region; diff --git a/include/linux/pci.h b/include/linux/pci.h index 98bdd95fcee9..8621cf42b46f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -225,7 +225,6 @@ #define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */ #define PCI_PM_CTRL 4 /* PM control and status register */ #define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ -#define PCI_PM_CTRL_NO_SOFT_RESET 0x0004 /* No reset for D3hot->D0 */ #define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */ #define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ #define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ @@ -817,9 +816,7 @@ int pci_set_mwi(struct pci_dev *dev); void pci_clear_mwi(struct pci_dev *dev); int pci_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); -void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); int pci_assign_resource(struct pci_dev *dev, int i); -void pci_restore_bars(struct pci_dev *dev); /* ROM control related routines */ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size); -- cgit v1.2.3 From 00dd1e433967872f3997a45d5adf35056fdf2f56 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Mon, 8 Aug 2005 22:13:05 -0400 Subject: [PATCH] fsnotify-cleanups This removes the now unused fsnotify_unlink & fsnotify_rmdir code. Compile tested. Signed-off-by: John McCutchan Signed-off-by: Linus Torvalds --- include/linux/fsnotify.h | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 9db31d251c20..602c305c8585 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -43,30 +43,6 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, } } -/* - * fsnotify_unlink - file was unlinked - */ -static inline void fsnotify_unlink(struct dentry *dentry, struct inode *inode, struct inode *dir) -{ - inode_dir_notify(dir, DN_DELETE); - inotify_inode_queue_event(dir, IN_DELETE, 0, dentry->d_name.name); - inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL); - - inotify_inode_is_dead(inode); -} - -/* - * fsnotify_rmdir - directory was removed - */ -static inline void fsnotify_rmdir(struct dentry *dentry, struct inode *inode, - struct inode *dir) -{ - inode_dir_notify(dir, DN_DELETE); - inotify_inode_queue_event(dir,IN_DELETE|IN_ISDIR,0,dentry->d_name.name); - inotify_inode_queue_event(inode, IN_DELETE_SELF | IN_ISDIR, 0, NULL); - inotify_inode_is_dead(inode); -} - /* * fsnotify_nameremove - a filename was removed from a directory */ -- cgit v1.2.3 From 5bb8345db8f2aef367e0fddf99a42b7a6029b31f Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Tue, 9 Aug 2005 12:57:58 -0400 Subject: [SCSI] dpt_i2o pci_request_regions fix Originally From: Andrew Morton Altered By: "Salyzyn, Mark" There is an additional 'build fix' patch that Andrew Morton submitted on the kernel list (I have changed out his dpr_i2o with dpt_i2o below though). Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/dpt_i2o.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index bc7b84c95db6..7235f94f1191 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -907,7 +907,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev raptorFlag = TRUE; } - if (pci_request_regions(pDev)) { + if (pci_request_regions(pDev, "dpt_i2o")) { PERROR("dpti: adpt_config_hba: pci request region failed\n"); return -EINVAL; } -- cgit v1.2.3 From 01df0e3a79d3913df178e9a1047ade425a7c118f Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Tue, 9 Aug 2005 10:07:56 -0700 Subject: [PATCH] i8xx_tco.c: arm watchdog only when started i8xx_tco.c v0.08: only "arm" the watchdog when the watchdog has been started. (Kernel Bug 4251: system reset when battery is read and i8xx_tco driver loaded) Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/watchdog/i8xx_tco.c | 41 +++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index f975dab1ddf9..a13395e2c372 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c @@ -1,5 +1,5 @@ /* - * i8xx_tco 0.07: TCO timer driver for i8xx chipsets + * i8xx_tco: TCO timer driver for i8xx chipsets * * (c) Copyright 2000 kernel concepts , All Rights Reserved. * http://www.kernelconcepts.de @@ -63,6 +63,9 @@ * 20050128 Wim Van Sebroeck * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW * chipsets. Also added support for the "undocumented" ICH7 chipset. + * 20050807 Wim Van Sebroeck + * 0.08 Make sure that the watchdog is only "armed" when started. + * (Kernel Bug 4251) */ /* @@ -87,7 +90,7 @@ #include "i8xx_tco.h" /* Module and version information */ -#define TCO_VERSION "0.07" +#define TCO_VERSION "0.08" #define TCO_MODULE_NAME "i8xx TCO timer" #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION #define PFX TCO_MODULE_NAME ": " @@ -125,10 +128,18 @@ static int tco_timer_start (void) unsigned char val; spin_lock(&tco_lock); + + /* disable chipset's NO_REBOOT bit */ + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val); + val &= 0xfd; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val); + + /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */ val = inb (TCO1_CNT + 1); val &= 0xf7; outb (val, TCO1_CNT + 1); val = inb (TCO1_CNT + 1); + spin_unlock(&tco_lock); if (val & 0x08) @@ -138,13 +149,20 @@ static int tco_timer_start (void) static int tco_timer_stop (void) { - unsigned char val; + unsigned char val, val1; spin_lock(&tco_lock); + /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ val = inb (TCO1_CNT + 1); val |= 0x08; outb (val, TCO1_CNT + 1); val = inb (TCO1_CNT + 1); + + /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); + val1 |= 0x02; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); + spin_unlock(&tco_lock); if ((val & 0x08) == 0) @@ -155,6 +173,7 @@ static int tco_timer_stop (void) static int tco_timer_keepalive (void) { spin_lock(&tco_lock); + /* Reload the timer by writing to the TCO Timer Reload register */ outb (0x01, TCO1_RLD); spin_unlock(&tco_lock); return 0; @@ -417,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void) printk (KERN_ERR PFX "failed to get TCOBASE address\n"); return 0; } - /* - * Check chipset's NO_REBOOT bit - */ + + /* Check chipset's NO_REBOOT bit */ pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); if (val1 & 0x02) { val1 &= 0xfd; @@ -430,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void) return 0; /* Cannot reset NO_REBOOT bit */ } } + /* Disable reboots untill the watchdog starts */ + val1 |= 0x02; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); + /* Set the TCO_EN bit in SMI_EN register */ if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", @@ -505,17 +527,10 @@ out: static void __exit watchdog_cleanup (void) { - u8 val; - /* Stop the timer before we leave */ if (!nowayout) tco_timer_stop (); - /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ - pci_read_config_byte (i8xx_tco_pci, 0xd4, &val); - val |= 0x02; - pci_write_config_byte (i8xx_tco_pci, 0xd4, val); - /* Deregister */ misc_deregister (&i8xx_tco_miscdev); unregister_reboot_notifier(&i8xx_tco_notifier); -- cgit v1.2.3 From a242b44da6feb604c4c659b78f63dedb69b2d4a3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 9 Aug 2005 10:07:57 -0700 Subject: [PATCH] Build fix for the Sibyte I2C driver Compile fix for the BCM1250 I2C driver. Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/i2c/busses/i2c-sibyte.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 1c99536b673b..fa503ed9f86d 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -23,8 +23,8 @@ #include static struct i2c_algo_sibyte_data sibyte_board_data[2] = { - { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) }, - { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) } + { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) }, + { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) } }; static struct i2c_adapter sibyte_board_adapter[2] = { -- cgit v1.2.3 From 3077a260e9f316b611436b1506eec9cc5c4f8aa6 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Tue, 9 Aug 2005 10:07:59 -0700 Subject: [PATCH] cpuset release ABBA deadlock fix Fix possible cpuset_sem ABBA deadlock if 'notify_on_release' set. For a particular usage pattern, creating and destroying cpusets fairly frequently using notify_on_release, on a very large system, this deadlock can be seen every few days. If you are not using the cpuset notify_on_release feature, you will never see this deadlock. The existing code, on task exit (or cpuset deletion) did: get cpuset_sem if cpuset marked notify_on_release and is ready to release: compute cpuset path relative to /dev/cpuset mount point call_usermodehelper() forks /sbin/cpuset_release_agent with path drop cpuset_sem Unfortunately, the fork in call_usermodehelper can allocate memory, and allocating memory can require cpuset_sem, if the mems_generation values changed in the interim. This results in an ABBA deadlock, trying to obtain cpuset_sem when it is already held by the current task. To fix this, I put the cpuset path (which must be computed while holding cpuset_sem) in a temporary buffer, to be used in the call_usermodehelper call of /sbin/cpuset_release_agent only _after_ dropping cpuset_sem. So the new logic is: get cpuset_sem if cpuset marked notify_on_release and is ready to release: compute cpuset path relative to /dev/cpuset mount point stash path in kmalloc'd buffer drop cpuset_sem call_usermodehelper() forks /sbin/cpuset_release_agent with path free path The sharp eyed reader might notice that this patch does not contain any calls to kmalloc. The existing code in the check_for_release() routine was already kmalloc'ing a buffer to hold the cpuset path. In the old code, it just held the buffer for a few lines, over the cpuset_release_agent() call that in turn invoked call_usermodehelper(). In the new code, with the application of this patch, it returns that buffer via the new char **ppathbuf parameter, for later use and freeing in cpuset_release_agent(), which is called after cpuset_sem is dropped. Whereas the old code has just one call to cpuset_release_agent(), right in the check_for_release() routine, the new code has three calls to cpuset_release_agent(), from the various places that a cpuset can be released. This patch has been build and booted on SN2, and passed a stress test that previously hit the deadlock within a few seconds. Signed-off-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/cpuset.c | 68 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 805fb9097318..21a4e3b2cbda 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -398,21 +398,31 @@ static int cpuset_path(const struct cpuset *cs, char *buf, int buflen) * to continue to serve a useful existence. Next time it's released, * we will get notified again, if it still has 'notify_on_release' set. * - * Note final arg to call_usermodehelper() is 0 - that means - * don't wait. Since we are holding the global cpuset_sem here, - * and we are asking another thread (started from keventd) to rmdir a - * cpuset, we can't wait - or we'd deadlock with the removing thread - * on cpuset_sem. + * The final arg to call_usermodehelper() is 0, which means don't + * wait. The separate /sbin/cpuset_release_agent task is forked by + * call_usermodehelper(), then control in this thread returns here, + * without waiting for the release agent task. We don't bother to + * wait because the caller of this routine has no use for the exit + * status of the /sbin/cpuset_release_agent task, so no sense holding + * our caller up for that. + * + * The simple act of forking that task might require more memory, + * which might need cpuset_sem. So this routine must be called while + * cpuset_sem is not held, to avoid a possible deadlock. See also + * comments for check_for_release(), below. */ -static int cpuset_release_agent(char *cpuset_str) +static void cpuset_release_agent(const char *pathbuf) { char *argv[3], *envp[3]; int i; + if (!pathbuf) + return; + i = 0; argv[i++] = "/sbin/cpuset_release_agent"; - argv[i++] = cpuset_str; + argv[i++] = (char *)pathbuf; argv[i] = NULL; i = 0; @@ -421,17 +431,29 @@ static int cpuset_release_agent(char *cpuset_str) envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp[i] = NULL; - return call_usermodehelper(argv[0], argv, envp, 0); + call_usermodehelper(argv[0], argv, envp, 0); + kfree(pathbuf); } /* * Either cs->count of using tasks transitioned to zero, or the * cs->children list of child cpusets just became empty. If this * cs is notify_on_release() and now both the user count is zero and - * the list of children is empty, send notice to user land. + * the list of children is empty, prepare cpuset path in a kmalloc'd + * buffer, to be returned via ppathbuf, so that the caller can invoke + * cpuset_release_agent() with it later on, once cpuset_sem is dropped. + * Call here with cpuset_sem held. + * + * This check_for_release() routine is responsible for kmalloc'ing + * pathbuf. The above cpuset_release_agent() is responsible for + * kfree'ing pathbuf. The caller of these routines is responsible + * for providing a pathbuf pointer, initialized to NULL, then + * calling check_for_release() with cpuset_sem held and the address + * of the pathbuf pointer, then dropping cpuset_sem, then calling + * cpuset_release_agent() with pathbuf, as set by check_for_release(). */ -static void check_for_release(struct cpuset *cs) +static void check_for_release(struct cpuset *cs, char **ppathbuf) { if (notify_on_release(cs) && atomic_read(&cs->count) == 0 && list_empty(&cs->children)) { @@ -441,10 +463,9 @@ static void check_for_release(struct cpuset *cs) if (!buf) return; if (cpuset_path(cs, buf, PAGE_SIZE) < 0) - goto out; - cpuset_release_agent(buf); -out: - kfree(buf); + kfree(buf); + else + *ppathbuf = buf; } } @@ -727,14 +748,14 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) return 0; } -static int attach_task(struct cpuset *cs, char *buf) +static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf) { pid_t pid; struct task_struct *tsk; struct cpuset *oldcs; cpumask_t cpus; - if (sscanf(buf, "%d", &pid) != 1) + if (sscanf(pidbuf, "%d", &pid) != 1) return -EIO; if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)) return -ENOSPC; @@ -777,7 +798,7 @@ static int attach_task(struct cpuset *cs, char *buf) put_task_struct(tsk); if (atomic_dec_and_test(&oldcs->count)) - check_for_release(oldcs); + check_for_release(oldcs, ppathbuf); return 0; } @@ -801,6 +822,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us struct cftype *cft = __d_cft(file->f_dentry); cpuset_filetype_t type = cft->private; char *buffer; + char *pathbuf = NULL; int retval = 0; /* Crude upper limit on largest legitimate cpulist user might write. */ @@ -841,7 +863,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer); break; case FILE_TASKLIST: - retval = attach_task(cs, buffer); + retval = attach_task(cs, buffer, &pathbuf); break; default: retval = -EINVAL; @@ -852,6 +874,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us retval = nbytes; out2: up(&cpuset_sem); + cpuset_release_agent(pathbuf); out1: kfree(buffer); return retval; @@ -1357,6 +1380,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) struct cpuset *cs = dentry->d_fsdata; struct dentry *d; struct cpuset *parent; + char *pathbuf = NULL; /* the vfs holds both inode->i_sem already */ @@ -1376,7 +1400,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) update_cpu_domains(cs); list_del(&cs->sibling); /* delete my sibling from parent->children */ if (list_empty(&parent->children)) - check_for_release(parent); + check_for_release(parent, &pathbuf); spin_lock(&cs->dentry->d_lock); d = dget(cs->dentry); cs->dentry = NULL; @@ -1384,6 +1408,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) cpuset_d_remove_dir(d); dput(d); up(&cpuset_sem); + cpuset_release_agent(pathbuf); return 0; } @@ -1483,10 +1508,13 @@ void cpuset_exit(struct task_struct *tsk) task_unlock(tsk); if (notify_on_release(cs)) { + char *pathbuf = NULL; + down(&cpuset_sem); if (atomic_dec_and_test(&cs->count)) - check_for_release(cs); + check_for_release(cs, &pathbuf); up(&cpuset_sem); + cpuset_release_agent(pathbuf); } else { atomic_dec(&cs->count); } -- cgit v1.2.3 From 311c46273f0e8b140d4cc68e13128cbc22114807 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 9 Aug 2005 10:08:00 -0700 Subject: [PATCH] cpm_uart: Fix dpram allocation and non-console uarts * Makes dpram allocations work * Makes non-console UART work on both 8xx and 82xx * Fixed whitespace in files that were touched Signed-off-by: Vitaly Bordug Signed-off-by: Pantelis Antoniou Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/cpm_uart/cpm_uart.h | 10 ++- drivers/serial/cpm_uart/cpm_uart_core.c | 118 ++++++++++++++++++++++---------- drivers/serial/cpm_uart/cpm_uart_cpm1.c | 53 +++++++------- 3 files changed, 116 insertions(+), 65 deletions(-) diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 5f6187baad86..73c8a088c160 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h @@ -40,13 +40,15 @@ #define TX_NUM_FIFO 4 #define TX_BUF_SIZE 32 +#define SCC_WAIT_CLOSING 100 + struct uart_cpm_port { struct uart_port port; - u16 rx_nrfifos; + u16 rx_nrfifos; u16 rx_fifosize; - u16 tx_nrfifos; + u16 tx_nrfifos; u16 tx_fifosize; - smc_t *smcp; + smc_t *smcp; smc_uart_t *smcup; scc_t *sccp; scc_uart_t *sccup; @@ -67,6 +69,8 @@ struct uart_cpm_port { int bits; /* Keep track of 'odd' SMC2 wirings */ int is_portb; + /* wait on close if needed */ + int wait_closing; }; extern int cpm_uart_port_map[UART_NR]; diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 29db677d4284..8bd2885b0d32 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -9,9 +9,10 @@ * * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) * Pantelis Antoniou (panto@intracom.gr) (CPM1) - * + * * Copyright (C) 2004 Freescale Semiconductor, Inc. * (C) 2004 Intracom, S.A. + * (C) 2005 MontaVista Software, Inc. by Vitaly Bordug * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -70,8 +71,22 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); /**************************************************************/ +static inline unsigned long cpu2cpm_addr(void *addr) +{ + if ((unsigned long)addr >= CPM_ADDR) + return (unsigned long)addr; + return virt_to_bus(addr); +} + +static inline void *cpm2cpu_addr(unsigned long addr) +{ + if (addr >= CPM_ADDR) + return (void *)addr; + return bus_to_virt(addr); +} + /* - * Check, if transmit buffers are processed + * Check, if transmit buffers are processed */ static unsigned int cpm_uart_tx_empty(struct uart_port *port) { @@ -143,15 +158,18 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start) } if (cpm_uart_tx_pump(port) != 0) { - if (IS_SMC(pinfo)) + if (IS_SMC(pinfo)) { smcp->smc_smcm |= SMCM_TX; - else + smcp->smc_smcmr |= SMCMR_TEN; + } else { sccp->scc_sccm |= UART_SCCM_TX; + pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT; + } } } /* - * Stop receiver + * Stop receiver */ static void cpm_uart_stop_rx(struct uart_port *port) { @@ -176,7 +194,7 @@ static void cpm_uart_enable_ms(struct uart_port *port) } /* - * Generate a break. + * Generate a break. */ static void cpm_uart_break_ctl(struct uart_port *port, int break_state) { @@ -231,7 +249,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) /* get number of characters, and check spce in flip-buffer */ i = bdp->cbd_datlen; - /* If we have not enough room in tty flip buffer, then we try + /* If we have not enough room in tty flip buffer, then we try * later, which will be the next rx-interrupt or a timeout */ if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) { @@ -243,7 +261,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) } /* get pointer */ - cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr); + cp = cpm2cpu_addr(bdp->cbd_bufaddr); /* loop through the buffer */ while (i-- > 0) { @@ -265,13 +283,14 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) } /* End while (i--) */ /* This BD is ready to be used again. Clear status. get next */ - bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV); + bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID); bdp->cbd_sc |= BD_SC_EMPTY; if (bdp->cbd_sc & BD_SC_WRAP) bdp = pinfo->rx_bd_base; else bdp++; + } /* End for (;;) */ /* Write back buffer pointer */ @@ -336,22 +355,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs) if (IS_SMC(pinfo)) { events = smcp->smc_smce; + smcp->smc_smce = events; if (events & SMCM_BRKE) uart_handle_break(port); if (events & SMCM_RX) cpm_uart_int_rx(port, regs); if (events & SMCM_TX) cpm_uart_int_tx(port, regs); - smcp->smc_smce = events; } else { events = sccp->scc_scce; + sccp->scc_scce = events; if (events & UART_SCCM_BRKE) uart_handle_break(port); if (events & UART_SCCM_RX) cpm_uart_int_rx(port, regs); if (events & UART_SCCM_TX) cpm_uart_int_tx(port, regs); - sccp->scc_scce = events; } return (events) ? IRQ_HANDLED : IRQ_NONE; } @@ -360,6 +379,7 @@ static int cpm_uart_startup(struct uart_port *port) { int retval; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; + int line = pinfo - cpm_uart_ports; pr_debug("CPM uart[%d]:startup\n", port->line); @@ -376,9 +396,19 @@ static int cpm_uart_startup(struct uart_port *port) pinfo->sccp->scc_sccm |= UART_SCCM_RX; } + if (!(pinfo->flags & FLAG_CONSOLE)) + cpm_line_cr_cmd(line,CPM_CR_INIT_TRX); return 0; } +inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo) +{ + unsigned long target_jiffies = jiffies + pinfo->wait_closing; + + while (!time_after(jiffies, target_jiffies)) + schedule(); +} + /* * Shutdown the uart */ @@ -394,6 +424,12 @@ static void cpm_uart_shutdown(struct uart_port *port) /* If the port is not the console, disable Rx and Tx. */ if (!(pinfo->flags & FLAG_CONSOLE)) { + /* Wait for all the BDs marked sent */ + while(!cpm_uart_tx_empty(port)) + schedule_timeout(2); + if(pinfo->wait_closing) + cpm_uart_wait_until_send(pinfo); + /* Stop uarts */ if (IS_SMC(pinfo)) { volatile smc_t *smcp = pinfo->smcp; @@ -502,7 +538,7 @@ static void cpm_uart_set_termios(struct uart_port *port, */ if ((termios->c_cflag & CREAD) == 0) port->read_status_mask &= ~BD_SC_EMPTY; - + spin_lock_irqsave(&port->lock, flags); /* Start bit has not been added (so don't, because we would just @@ -569,7 +605,8 @@ static int cpm_uart_tx_pump(struct uart_port *port) /* Pick next descriptor and fill from buffer */ bdp = pinfo->tx_cur; - p = bus_to_virt(bdp->cbd_bufaddr); + p = cpm2cpu_addr(bdp->cbd_bufaddr); + *p++ = xmit->buf[xmit->tail]; bdp->cbd_datlen = 1; bdp->cbd_sc |= BD_SC_READY; @@ -595,7 +632,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { count = 0; - p = bus_to_virt(bdp->cbd_bufaddr); + p = cpm2cpu_addr(bdp->cbd_bufaddr); while (count < pinfo->tx_fifosize) { *p++ = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -606,6 +643,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) } bdp->cbd_datlen = count; bdp->cbd_sc |= BD_SC_READY; + __asm__("eieio"); /* Get next BD. */ if (bdp->cbd_sc & BD_SC_WRAP) bdp = pinfo->tx_bd_base; @@ -643,12 +681,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) mem_addr = pinfo->mem_addr; bdp = pinfo->rx_cur = pinfo->rx_bd_base; for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { - bdp->cbd_bufaddr = virt_to_bus(mem_addr); + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; mem_addr += pinfo->rx_fifosize; } - - bdp->cbd_bufaddr = virt_to_bus(mem_addr); + + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; /* Set the physical address of the host memory @@ -658,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); bdp = pinfo->tx_cur = pinfo->tx_bd_base; for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { - bdp->cbd_bufaddr = virt_to_bus(mem_addr); + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); bdp->cbd_sc = BD_SC_INTRPT; mem_addr += pinfo->tx_fifosize; } - - bdp->cbd_bufaddr = virt_to_bus(mem_addr); + + bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr); bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; } @@ -763,6 +801,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) /* Using idle charater time requires some additional tuning. */ up->smc_mrblr = pinfo->rx_fifosize; up->smc_maxidl = pinfo->rx_fifosize; + up->smc_brklen = 0; + up->smc_brkec = 0; up->smc_brkcr = 1; cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); @@ -796,7 +836,7 @@ static int cpm_uart_request_port(struct uart_port *port) /* * Setup any port IO, connect any baud rate generators, * etc. This is expected to be handled by board - * dependant code + * dependant code */ if (pinfo->set_lineif) pinfo->set_lineif(pinfo); @@ -815,6 +855,10 @@ static int cpm_uart_request_port(struct uart_port *port) return ret; cpm_uart_initbd(pinfo); + if (IS_SMC(pinfo)) + cpm_uart_init_smc(pinfo); + else + cpm_uart_init_scc(pinfo); return 0; } @@ -869,7 +913,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .flags = FLAG_SMC, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = smc1_lineif, }, @@ -883,7 +927,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { .flags = FLAG_SMC, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = smc2_lineif, #ifdef CONFIG_SERIAL_CPM_ALT_SMC2 @@ -899,9 +943,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = scc1_lineif, + .wait_closing = SCC_WAIT_CLOSING, }, [UART_SCC2] = { .port = { @@ -912,9 +957,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = scc2_lineif, + .wait_closing = SCC_WAIT_CLOSING, }, [UART_SCC3] = { .port = { @@ -925,9 +971,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = scc3_lineif, + .wait_closing = SCC_WAIT_CLOSING, }, [UART_SCC4] = { .port = { @@ -938,9 +985,10 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { }, .tx_nrfifos = TX_NUM_FIFO, .tx_fifosize = TX_BUF_SIZE, - .rx_nrfifos = RX_NUM_FIFO, + .rx_nrfifos = RX_NUM_FIFO, .rx_fifosize = RX_BUF_SIZE, .set_lineif = scc4_lineif, + .wait_closing = SCC_WAIT_CLOSING, }, }; @@ -983,11 +1031,8 @@ static void cpm_uart_console_write(struct console *co, const char *s, * If the buffer address is in the CPM DPRAM, don't * convert it. */ - if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) - cp = (unsigned char *) (bdp->cbd_bufaddr); - else - cp = bus_to_virt(bdp->cbd_bufaddr); - + cp = cpm2cpu_addr(bdp->cbd_bufaddr); + *cp = *s; bdp->cbd_datlen = 1; @@ -1003,10 +1048,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, while ((bdp->cbd_sc & BD_SC_READY) != 0) ; - if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) - cp = (unsigned char *) (bdp->cbd_bufaddr); - else - cp = bus_to_virt(bdp->cbd_bufaddr); + cp = cpm2cpu_addr(bdp->cbd_bufaddr); *cp = 13; bdp->cbd_datlen = 1; @@ -1045,7 +1087,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) port = (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; pinfo = (struct uart_cpm_port *)port; - + pinfo->flags |= FLAG_CONSOLE; if (options) { @@ -1062,7 +1104,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) /* * Setup any port IO, connect any baud rate generators, * etc. This is expected to be handled by board - * dependant code + * dependant code */ if (pinfo->set_lineif) pinfo->set_lineif(pinfo); diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 8efbd6d1d6a4..4b0786e7eb7f 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c @@ -5,7 +5,7 @@ * * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) * Pantelis Antoniou (panto@intracom.gr) (CPM1) - * + * * Copyright (C) 2004 Freescale Semiconductor, Inc. * (C) 2004 Intracom, S.A. * @@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd) void smc1_lineif(struct uart_cpm_port *pinfo) { volatile cpm8xx_t *cp = cpmp; + + (void)cp; /* fix warning */ +#if defined (CONFIG_MPC885ADS) + /* Enable SMC1 transceivers */ + { + cp->cp_pepar |= 0x000000c0; + cp->cp_pedir &= ~0x000000c0; + cp->cp_peso &= ~0x00000040; + cp->cp_peso |= 0x00000080; + } +#elif defined (CONFIG_MPC86XADS) unsigned int iobits = 0x000000c0; if (!pinfo->is_portb) { @@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo) ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; } - -#ifdef CONFIG_MPC885ADS - /* Enable SMC1 transceivers */ - { - volatile uint __iomem *bcsr1 = ioremap(BCSR1, 4); - uint tmp; - - tmp = in_be32(bcsr1); - tmp &= ~BCSR1_RS232EN_1; - out_be32(bcsr1, tmp); - iounmap(bcsr1); - } #endif - pinfo->brg = 1; } void smc2_lineif(struct uart_cpm_port *pinfo) { -#ifdef CONFIG_MPC885ADS volatile cpm8xx_t *cp = cpmp; - volatile uint __iomem *bcsr1; - uint tmp; + (void)cp; /* fix warning */ +#if defined (CONFIG_MPC885ADS) cp->cp_pepar |= 0x00000c00; cp->cp_pedir &= ~0x00000c00; cp->cp_peso &= ~0x00000400; cp->cp_peso |= 0x00000800; +#elif defined (CONFIG_MPC86XADS) + unsigned int iobits = 0x00000c00; + + if (!pinfo->is_portb) { + cp->cp_pbpar |= iobits; + cp->cp_pbdir &= ~iobits; + cp->cp_pbodr &= ~iobits; + } else { + ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits; + ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; + ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; + } - /* Enable SMC2 transceivers */ - bcsr1 = ioremap(BCSR1, 4); - tmp = in_be32(bcsr1); - tmp &= ~BCSR1_RS232EN_2; - out_be32(bcsr1, tmp); - iounmap(bcsr1); #endif pinfo->brg = 2; @@ -158,7 +161,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo) } /* - * Allocate DP-Ram and memory buffers. We need to allocate a transmit and + * Allocate DP-Ram and memory buffers. We need to allocate a transmit and * receive buffer descriptors from dual port ram, and a character * buffer area from host mem. If we are allocating for the console we need * to do it from bootmem @@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); if (is_con) { + /* was hostalloc but changed cause it blows away the */ + /* large tlb mapping when pinning the kernel area */ mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); dma_addr = 0; } else -- cgit v1.2.3 From 36d2f5a18205dfc2fac1e3541d324ce186f418cb Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 9 Aug 2005 10:08:02 -0700 Subject: [PATCH] cpm_uart: needs some love to compile with GCC4.0.1 Fixed problems so we can build with gcc-4.0.1 Signed-off-by: Peter Schaefer-Hutter Signed-off-by: Kumar Gala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/cpm_uart/cpm_uart_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 8bd2885b0d32..d639ac92a117 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -1134,14 +1134,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) return 0; } -extern struct uart_driver cpm_reg; +static struct uart_driver cpm_reg; static struct console cpm_scc_uart_console = { - .name "ttyCPM", - .write cpm_uart_console_write, - .device uart_console_device, - .setup cpm_uart_console_setup, - .flags CON_PRINTBUFFER, - .index -1, + .name = "ttyCPM", + .write = cpm_uart_console_write, + .device = uart_console_device, + .setup = cpm_uart_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, .data = &cpm_reg, }; -- cgit v1.2.3 From db29e85a7ece62de1899917c1ec0ffe55cf1d3a0 Mon Sep 17 00:00:00 2001 From: Markus Lidel Date: Tue, 9 Aug 2005 10:08:03 -0700 Subject: [PATCH] i2o: remove new configuration API Remove new configuration API from i2o_config The API-patch is still available from the I2O website (which is mentioned in the kernel config now). It is removed because it creates a new binary sysfs-attribute, which doesn't have the limitiation of 4k. Expect for the Adaptec controllers, which has a limitation in the hardware this attribute doesn't make sense anywhere else. Until the sysfs API provides an attribute which doesn't buffer (like firmware) and let access to at least 64k blocks i provide a separate patch... (akpm: basically, this API was introduced post-2.6.12 and Markus wants to pull it out before 2.6.13). Signed-off-by: Markus Lidel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/Kconfig | 3 + drivers/message/i2o/config-osm.c | 494 --------------------------------------- 2 files changed, 3 insertions(+), 494 deletions(-) diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig index 06e8eb19a05c..43a942a29c2e 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/message/i2o/Kconfig @@ -53,6 +53,9 @@ config I2O_CONFIG To compile this support as a module, choose M here: the module will be called i2o_config. + Note: If you want to use the new API you have to download the + i2o_config patch from http://i2o.shadowconnect.com/ + config I2O_CONFIG_OLD_IOCTL bool "Enable ioctls (OBSOLETE)" depends on I2O_CONFIG diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c index fe2e7afc9eae..af32ab4e90cd 100644 --- a/drivers/message/i2o/config-osm.c +++ b/drivers/message/i2o/config-osm.c @@ -30,503 +30,9 @@ static struct i2o_driver i2o_config_driver; -/* Special file operations for sysfs */ -struct fops_attribute { - struct bin_attribute bin; - struct file_operations fops; -}; - -/** - * sysfs_read_dummy - */ -static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset, - size_t count) -{ - return 0; -}; - -/** - * sysfs_write_dummy - */ -static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset, - size_t count) -{ - return 0; -}; - -/** - * sysfs_create_fops_file - Creates attribute with special file operations - * @kobj: kobject which should contains the attribute - * @attr: attributes which should be used to create file - * - * First creates attribute @attr in kobject @kobj. If it is the first time - * this function is called, merge old fops from sysfs with new one and - * write it back. Afterwords the new fops will be set for the created - * attribute. - * - * Returns 0 on success or negative error code on failure. - */ -static int sysfs_create_fops_file(struct kobject *kobj, - struct fops_attribute *attr) -{ - struct file_operations tmp, *fops; - struct dentry *d; - struct qstr qstr; - int rc; - - fops = &attr->fops; - - if (fops->read) - attr->bin.read = sysfs_read_dummy; - - if (fops->write) - attr->bin.write = sysfs_write_dummy; - - if ((rc = sysfs_create_bin_file(kobj, &attr->bin))) - return rc; - - qstr.name = attr->bin.attr.name; - qstr.len = strlen(qstr.name); - qstr.hash = full_name_hash(qstr.name, qstr.len); - - if ((d = lookup_hash(&qstr, kobj->dentry))) { - if (!fops->owner) { - memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp)); - if (fops->read) - tmp.read = fops->read; - if (fops->write) - tmp.write = fops->write; - memcpy(fops, &tmp, sizeof(tmp)); - } - - d->d_inode->i_fop = fops; - } else - sysfs_remove_bin_file(kobj, &attr->bin); - - return -ENOENT; -}; - -/** - * sysfs_remove_fops_file - Remove attribute with special file operations - * @kobj: kobject which contains the attribute - * @attr: attributes which are used to create file - * - * Only wrapper arround sysfs_remove_bin_file() - * - * Returns 0 on success or negative error code on failure. - */ -static inline int sysfs_remove_fops_file(struct kobject *kobj, - struct fops_attribute *attr) -{ - return sysfs_remove_bin_file(kobj, &attr->bin); -}; - -/** - * i2o_config_read_hrt - Returns the HRT of the controller - * @kob: kernel object handle - * @buf: buffer into which the HRT should be copied - * @off: file offset - * @count: number of bytes to read - * - * Put @count bytes starting at @off into @buf from the HRT of the I2O - * controller corresponding to @kobj. - * - * Returns number of bytes copied into buffer. - */ -static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf, - loff_t offset, size_t count) -{ - struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; - i2o_hrt *hrt = c->hrt.virt; - - u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4; - - if (offset > size) - return 0; - - if (offset + count > size) - count = size - offset; - - memcpy(buf, (u8 *) hrt + offset, count); - - return count; -}; - -/** - * i2o_config_read_lct - Returns the LCT of the controller - * @kob: kernel object handle - * @buf: buffer into which the LCT should be copied - * @off: file offset - * @count: number of bytes to read - * - * Put @count bytes starting at @off into @buf from the LCT of the I2O - * controller corresponding to @kobj. - * - * Returns number of bytes copied into buffer. - */ -static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf, - loff_t offset, size_t count) -{ - struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; - u32 size = c->lct->table_size * 4; - - if (offset > size) - return 0; - - if (offset + count > size) - count = size - offset; - - memcpy(buf, (u8 *) c->lct + offset, count); - - return count; -}; - -#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \ -static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \ - return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \ -};\ -\ -static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \ - return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \ -}; \ -\ -static struct fops_attribute i2o_config_attr_##_name = { \ - .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \ - .owner = THIS_MODULE }, \ - .size = 0, }, \ - .fops = { .write = i2o_config_##_name##_write, \ - .read = i2o_config_##_name##_read} \ -}; - -#ifdef CONFIG_I2O_EXT_ADAPTEC - -/** - * i2o_config_dpt_reagion - Converts type and id to flash region - * @swtype: type of software module reading - * @swid: id of software which should be read - * - * Converts type and id from I2O spec to the matching region for DPT / - * Adaptec controllers. - * - * Returns region which match type and id or -1 on error. - */ -static u32 i2o_config_dpt_region(u8 swtype, u8 swid) -{ - switch (swtype) { - case I2O_SOFTWARE_MODULE_IRTOS: - /* - * content: operation firmware - * region size: - * 0xbc000 for 2554, 3754, 2564, 3757 - * 0x170000 for 2865 - * 0x17c000 for 3966 - */ - if (!swid) - return 0; - - break; - - case I2O_SOFTWARE_MODULE_IOP_PRIVATE: - /* - * content: BIOS and SMOR - * BIOS size: first 0x8000 bytes - * region size: - * 0x40000 for 2554, 3754, 2564, 3757 - * 0x80000 for 2865, 3966 - */ - if (!swid) - return 1; - - break; - - case I2O_SOFTWARE_MODULE_IOP_CONFIG: - switch (swid) { - case 0: - /* - * content: NVRAM defaults - * region size: 0x2000 bytes - */ - return 2; - case 1: - /* - * content: serial number - * region size: 0x2000 bytes - */ - return 3; - } - break; - } - - return -1; -}; - -#endif - -/** - * i2o_config_sw_read - Read a software module from controller - * @file: file pointer - * @buf: buffer into which the data should be copied - * @count: number of bytes to read - * @off: file offset - * @swtype: type of software module reading - * @swid: id of software which should be read - * - * Transfers @count bytes at offset @offset from IOP into buffer using - * type @swtype and id @swid as described in I2O spec. - * - * Returns number of bytes copied into buffer or error code on failure. - */ -static ssize_t i2o_config_sw_read(struct file *file, char __user * buf, - size_t count, loff_t * offset, u8 swtype, - u32 swid) -{ - struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; - struct kobject *kobj = sd->s_element; - struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; - u32 m, function = I2O_CMD_SW_UPLOAD; - struct i2o_dma buffer; - struct i2o_message __iomem *msg; - u32 __iomem *mptr; - int rc, status; - - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -EBUSY; - - mptr = &msg->body[3]; - - if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) { - i2o_msg_nop(c, m); - return rc; - } -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - mptr = &msg->body[4]; - function = I2O_CMD_PRIVATE; - - writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); - - writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ, - &msg->body[0]); - writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); - writel(*offset, &msg->body[2]); - writel(count, &msg->body[3]); - } else -#endif - writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); - - writel(0xD0000000 | count, mptr++); - writel(buffer.phys, mptr); - - writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); - writel(i2o_config_driver.context, &msg->u.head[2]); - writel(0, &msg->u.head[3]); - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (!c->adaptec) -#endif - { - writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); - writel(0, &msg->body[1]); - writel(swid, &msg->body[2]); - } - - status = i2o_msg_post_wait_mem(c, m, 60, &buffer); - - if (status == I2O_POST_WAIT_OK) { - if (!(rc = copy_to_user(buf, buffer.virt, count))) { - rc = count; - *offset += count; - } - } else - rc = -EIO; - - if (status != -ETIMEDOUT) - i2o_dma_free(&c->pdev->dev, &buffer); - - return rc; -}; - -/** - * i2o_config_sw_write - Write a software module to controller - * @file: file pointer - * @buf: buffer into which the data should be copied - * @count: number of bytes to read - * @off: file offset - * @swtype: type of software module writing - * @swid: id of software which should be written - * - * Transfers @count bytes at offset @offset from buffer to IOP using - * type @swtype and id @swid as described in I2O spec. - * - * Returns number of bytes copied from buffer or error code on failure. - */ -static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf, - size_t count, loff_t * offset, u8 swtype, - u32 swid) -{ - struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata; - struct kobject *kobj = sd->s_element; - struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop; - u32 m, function = I2O_CMD_SW_DOWNLOAD; - struct i2o_dma buffer; - struct i2o_message __iomem *msg; - u32 __iomem *mptr; - int rc, status; - - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -EBUSY; - - mptr = &msg->body[3]; - - if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) - goto nop_msg; - - if ((rc = copy_from_user(buffer.virt, buf, count))) - goto free_buffer; - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - mptr = &msg->body[4]; - function = I2O_CMD_PRIVATE; - - writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]); - - writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE, - &msg->body[0]); - writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]); - writel(*offset, &msg->body[2]); - writel(count, &msg->body[3]); - } else -#endif - writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); - - writel(0xD4000000 | count, mptr++); - writel(buffer.phys, mptr); - - writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]); - writel(i2o_config_driver.context, &msg->u.head[2]); - writel(0, &msg->u.head[3]); - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (!c->adaptec) -#endif - { - writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]); - writel(0, &msg->body[1]); - writel(swid, &msg->body[2]); - } - - status = i2o_msg_post_wait_mem(c, m, 60, &buffer); - - if (status != -ETIMEDOUT) - i2o_dma_free(&c->pdev->dev, &buffer); - - if (status != I2O_POST_WAIT_OK) - return -EIO; - - *offset += count; - - return count; - - free_buffer: - i2o_dma_free(&c->pdev->dev, &buffer); - - nop_msg: - i2o_msg_nop(c, m); - - return rc; -}; - -/* attribute for HRT in sysfs */ -static struct bin_attribute i2o_config_hrt_attr = { - .attr = { - .name = "hrt", - .mode = S_IRUGO, - .owner = THIS_MODULE}, - .size = 0, - .read = i2o_config_read_hrt -}; - -/* attribute for LCT in sysfs */ -static struct bin_attribute i2o_config_lct_attr = { - .attr = { - .name = "lct", - .mode = S_IRUGO, - .owner = THIS_MODULE}, - .size = 0, - .read = i2o_config_read_lct -}; - -/* IRTOS firmware access */ -I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0); - -#ifdef CONFIG_I2O_EXT_ADAPTEC - -/* - * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec - * controllers - */ -I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0); -I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0); -I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1); - -#endif - -/** - * i2o_config_notify_controller_add - Notify of added controller - * @c: the controller which was added - * - * If a I2O controller is added, we catch the notification to add sysfs - * entries. - */ -static void i2o_config_notify_controller_add(struct i2o_controller *c) -{ - struct kobject *kobj = &c->exec->device.kobj; - - sysfs_create_bin_file(kobj, &i2o_config_hrt_attr); - sysfs_create_bin_file(kobj, &i2o_config_lct_attr); - - sysfs_create_fops_file(kobj, &i2o_config_attr_irtos); -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - sysfs_create_fops_file(kobj, &i2o_config_attr_bios); - sysfs_create_fops_file(kobj, &i2o_config_attr_nvram); - sysfs_create_fops_file(kobj, &i2o_config_attr_serial); - } -#endif -}; - -/** - * i2o_config_notify_controller_remove - Notify of removed controller - * @c: the controller which was removed - * - * If a I2O controller is removed, we catch the notification to remove the - * sysfs entries. - */ -static void i2o_config_notify_controller_remove(struct i2o_controller *c) -{ - struct kobject *kobj = &c->exec->device.kobj; - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - sysfs_remove_fops_file(kobj, &i2o_config_attr_serial); - sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram); - sysfs_remove_fops_file(kobj, &i2o_config_attr_bios); - } -#endif - sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos); - - sysfs_remove_bin_file(kobj, &i2o_config_lct_attr); - sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr); -}; - /* Config OSM driver struct */ static struct i2o_driver i2o_config_driver = { .name = OSM_NAME, - .notify_controller_add = i2o_config_notify_controller_add, - .notify_controller_remove = i2o_config_notify_controller_remove }; #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL -- cgit v1.2.3 From 218b29e0c3995ee15782de55ad1dd74cce1a728d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Aug 2005 12:30:07 -0700 Subject: [SPARC]: Use kthread infrastructure in envctrl envctrl currently uses very odd ways to stop a thread, using various things that should be exposed to drivers at all. This patch (which is untested as I don't have sparc hardware) switches it to use the proper kthread infrastructure. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/sbus/char/envctrl.c | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 9a8c572554f5..e103b12f9efe 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1010,16 +1011,13 @@ static int kenvctrld(void *__unused) poll_interval = 5000; /* TODO env_mon_interval */ - daemonize("kenvctrld"); - allow_signal(SIGKILL); - - kenvctrld_task = current; - printk(KERN_INFO "envctrl: %s starting...\n", current->comm); for (;;) { - if(msleep_interruptible(poll_interval)) - break; + msleep_interruptible(poll_interval); + if (kthread_should_stop()) + break; + for (whichcpu = 0; whichcpu < ENVCTRL_MAX_CPU; ++whichcpu) { if (0 < envctrl_read_cpu_info(whichcpu, cputemp, ENVCTRL_CPUTEMP_MON, @@ -1118,9 +1116,11 @@ done: i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); } - err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES); - if (err < 0) + kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); + if (IS_ERR(kenvctrld_task)) { + err = ERR_PTR(kenvctrld_task); goto out_deregister; + } return 0; @@ -1142,28 +1142,7 @@ static void __exit envctrl_cleanup(void) { int i; - if (NULL != kenvctrld_task) { - force_sig(SIGKILL, kenvctrld_task); - for (;;) { - struct task_struct *p; - int found = 0; - - read_lock(&tasklist_lock); - for_each_process(p) { - if (p == kenvctrld_task) { - found = 1; - break; - } - } - read_unlock(&tasklist_lock); - - if (!found) - break; - - msleep(1000); - } - kenvctrld_task = NULL; - } + kthread_stop(kenvctrld_task); iounmap(i2c); misc_deregister(&envctrl_dev); -- cgit v1.2.3 From bc2406684b5929cea5d40b9cc4fd872816956779 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Aug 2005 13:32:25 -0700 Subject: [SPARC]: Use kthread infrastructure in bbc_envctrl Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/sbus/char/bbc_envctrl.c | 39 ++++++++++----------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index b8a2c7353b0a..d44205d52bf3 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -7,6 +7,7 @@ #define __KERNEL_SYSCALLS__ #include +#include #include #include #include @@ -459,10 +460,6 @@ static struct task_struct *kenvctrld_task; static int kenvctrld(void *__unused) { - daemonize("kenvctrld"); - allow_signal(SIGKILL); - kenvctrld_task = current; - printk(KERN_INFO "bbc_envctrl: kenvctrld starting...\n"); last_warning_jiffies = jiffies - WARN_INTERVAL; for (;;) { @@ -470,7 +467,7 @@ static int kenvctrld(void *__unused) struct bbc_fan_control *fp; msleep_interruptible(POLL_INTERVAL); - if (signal_pending(current)) + if (kthread_should_stop()) break; for (tp = all_bbc_temps; tp; tp = tp->next) { @@ -577,7 +574,6 @@ int bbc_envctrl_init(void) int temp_index = 0; int fan_index = 0; int devidx = 0; - int err = 0; while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { if (!strcmp(echild->prom_name, "temperature")) @@ -585,9 +581,13 @@ int bbc_envctrl_init(void) if (!strcmp(echild->prom_name, "fan-control")) attach_one_fan(echild, fan_index++); } - if (temp_index != 0 && fan_index != 0) - err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES); - return err; + if (temp_index != 0 && fan_index != 0) { + kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); + if (IS_ERR(kenvctrld_task)) + return PTR_ERR(kenvctrld_task); + } + + return 0; } static void destroy_one_temp(struct bbc_cpu_temperature *tp) @@ -607,26 +607,7 @@ void bbc_envctrl_cleanup(void) struct bbc_cpu_temperature *tp; struct bbc_fan_control *fp; - if (kenvctrld_task != NULL) { - force_sig(SIGKILL, kenvctrld_task); - for (;;) { - struct task_struct *p; - int found = 0; - - read_lock(&tasklist_lock); - for_each_process(p) { - if (p == kenvctrld_task) { - found = 1; - break; - } - } - read_unlock(&tasklist_lock); - if (!found) - break; - msleep(1000); - } - kenvctrld_task = NULL; - } + kthread_stop(kenvctrld_task); tp = all_bbc_temps; while (tp != NULL) { -- cgit v1.2.3 From 4875ccdb304775e9fd830f644643a1513357e043 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Aug 2005 14:39:10 -0700 Subject: [SPARC]: remove ifdef CONFIG_PCI from envctrl.c The driver already depends on CONFIG_PCI in Kconfig. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/sbus/char/envctrl.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index e103b12f9efe..1247f81a3278 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1039,7 +1039,6 @@ static int kenvctrld(void *__unused) static int __init envctrl_init(void) { -#ifdef CONFIG_PCI struct linux_ebus *ebus = NULL; struct linux_ebus_device *edev = NULL; struct linux_ebus_child *edev_child = NULL; @@ -1133,9 +1132,6 @@ out_iounmap: kfree(i2c_childlist[i].tables); } return err; -#else - return -ENODEV; -#endif } static void __exit envctrl_cleanup(void) -- cgit v1.2.3 From 38c1844b3120e04b7f5bb9c18ebbc19883d1e1d6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 9 Aug 2005 14:43:14 -0700 Subject: [SPARC]: envctrl: ERR_PTR() --> PTR_ERR() Fix thinko in Christoph's changes. Signed-off-by: David S. Miller --- drivers/sbus/char/envctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 1247f81a3278..d765cc1bf060 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1117,7 +1117,7 @@ done: kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); if (IS_ERR(kenvctrld_task)) { - err = ERR_PTR(kenvctrld_task); + err = PTR_ERR(kenvctrld_task); goto out_deregister; } -- cgit v1.2.3 From 3501466941347f0e1992b2672affb3feb92925fd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 9 Aug 2005 14:57:12 -0700 Subject: [SUNRPC]: Fix nsec --> usec conversion. We need to divide, not multiply. While we're here, use NSEC_PER_USEC instead of a magic constant. Based upon a report from Josip Loncaric and a patch by Andrew Morton. Signed-off-by: David S. Miller --- net/sunrpc/svcsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 56db8f13e6cb..d0c3120d0233 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -586,7 +586,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) } if (skb->stamp.tv_sec == 0) { skb->stamp.tv_sec = xtime.tv_sec; - skb->stamp.tv_usec = xtime.tv_nsec * 1000; + skb->stamp.tv_usec = xtime.tv_nsec / NSEC_PER_USEC; /* Don't enable netstamp, sunrpc doesn't need that much accuracy */ } -- cgit v1.2.3 From d64d3873721cfe870d49d73c3744f06260779ce7 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 9 Aug 2005 15:29:19 -0700 Subject: [NET]: Fix memory leak in sys_{send,recv}msg() w/compat From: Dave Johnson sendmsg()/recvmsg() syscalls from o32/n32 apps to a 64bit kernel will cause a kernel memory leak if iov_len > UIO_FASTIOV for each syscall! This is because both sys_sendmsg() and verify_compat_iovec() kmalloc a new iovec structure. Only the one from sys_sendmsg() is free'ed. I wrote a simple test program to confirm this after identifying the problem: http://davej.org/programs/testsendmsg.c Note that the below fix will break solaris_sendmsg()/solaris_recvmsg() as it also calls verify_compat_iovec() but expects it to malloc internally. [ I fixed that. -DaveM ] Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- arch/sparc64/solaris/socket.c | 193 ++++++++++++++++++++++++++---------------- net/compat.c | 9 -- 2 files changed, 119 insertions(+), 83 deletions(-) diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c index 06740582717e..d3a66ea74a7f 100644 --- a/arch/sparc64/solaris/socket.c +++ b/arch/sparc64/solaris/socket.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -297,121 +298,165 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi { struct socket *sock; char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; + struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; unsigned char ctl[sizeof(struct cmsghdr) + 20]; unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; + struct msghdr msg_sys; + int err, ctl_len, iov_size, total_len; - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) + err = -EFAULT; + if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) + goto out; + + sock = sockfd_lookup(fd, &err); + if (!sock) goto out; + + /* do not move before msg_sys is valid */ + err = -EMSGSIZE; + if (msg_sys.msg_iovlen > UIO_MAXIOV) + goto out_put; + + /* Check whether to allocate the iovec area*/ + err = -ENOMEM; + iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); + if (msg_sys.msg_iovlen > UIO_FASTIOV) { + iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); + if (!iov) + goto out_put; + } + + err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); + if (err < 0) + goto out_freeiov; total_len = err; - if(kern_msg.msg_controllen) { - struct sol_cmsghdr __user *ucmsg = kern_msg.msg_control; + err = -ENOBUFS; + if (msg_sys.msg_controllen > INT_MAX) + goto out_freeiov; + + ctl_len = msg_sys.msg_controllen; + if (ctl_len) { + struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control; unsigned long *kcmsg; compat_size_t cmlen; - if (kern_msg.msg_controllen <= sizeof(compat_size_t)) - return -EINVAL; + err = -EINVAL; + if (ctl_len <= sizeof(compat_size_t)) + goto out_freeiov; - if(kern_msg.msg_controllen > sizeof(ctl)) { + if (ctl_len > sizeof(ctl)) { err = -ENOBUFS; - ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL); - if(!ctl_buf) + ctl_buf = kmalloc(ctl_len, GFP_KERNEL); + if (!ctl_buf) goto out_freeiov; } __get_user(cmlen, &ucmsg->cmsg_len); kcmsg = (unsigned long *) ctl_buf; *kcmsg++ = (unsigned long)cmlen; err = -EFAULT; - if(copy_from_user(kcmsg, &ucmsg->cmsg_level, - kern_msg.msg_controllen - sizeof(compat_size_t))) + if (copy_from_user(kcmsg, &ucmsg->cmsg_level, + ctl_len - sizeof(compat_size_t))) goto out_freectl; - kern_msg.msg_control = ctl_buf; + msg_sys.msg_control = ctl_buf; } - kern_msg.msg_flags = solaris_to_linux_msgflags(user_flags); + msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags); - lock_kernel(); - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - unlock_kernel(); + if (sock->file->f_flags & O_NONBLOCK) + msg_sys.msg_flags |= MSG_DONTWAIT; + err = sock_sendmsg(sock, &msg_sys, total_len); out_freectl: - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); + if (ctl_buf != ctl) + sock_kfree_s(sock->sk, ctl_buf, ctl_len); out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: + if (iov != iovstack) + sock_kfree_s(sock->sk, iov, iov_size); +out_put: + sockfd_put(sock); +out: return err; } asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags) { - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; struct socket *sock; + struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov = iovstack; + struct msghdr msg_sys; + unsigned long cmsg_ptr; + int err, iov_size, total_len, len; + + /* kernel mode address */ + char addr[MAX_SOCK_ADDR]; + + /* user mode address pointers */ struct sockaddr __user *uaddr; int __user *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) + if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - uaddr = kern_msg.msg_name; + sock = sockfd_lookup(fd, &err); + if (!sock) + goto out; + + err = -EMSGSIZE; + if (msg_sys.msg_iovlen > UIO_MAXIOV) + goto out_put; + + /* Check whether to allocate the iovec area*/ + err = -ENOMEM; + iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); + if (msg_sys.msg_iovlen > UIO_FASTIOV) { + iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); + if (!iov) + goto out_put; + } + + /* + * Save the user-mode address (verify_iovec will change the + * kernel msghdr to use the kernel address space) + */ + + uaddr = (void __user *) msg_sys.msg_name; uaddr_len = &user_msg->msg_namelen; - err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE); + err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); if (err < 0) - goto out; + goto out_freeiov; total_len = err; - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; + cmsg_ptr = (unsigned long) msg_sys.msg_control; + msg_sys.msg_flags = MSG_CMSG_COMPAT; - lock_kernel(); - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - err = sock_recvmsg(sock, &kern_msg, total_len, user_flags); - if(err >= 0) - len = err; - sockfd_put(sock); - } - unlock_kernel(); - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(err >= 0) { - err = __put_user(linux_to_solaris_msgflags(kern_msg.msg_flags), &user_msg->msg_flags); - if(!err) { - /* XXX Convert cmsg back into userspace 32-bit format... */ - err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr, - &user_msg->msg_controllen); - } + if (sock->file->f_flags & O_NONBLOCK) + user_flags |= MSG_DONTWAIT; + + err = sock_recvmsg(sock, &msg_sys, total_len, user_flags); + if(err < 0) + goto out_freeiov; + + len = err; + + if (uaddr != NULL) { + err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); + if (err < 0) + goto out_freeiov; } + err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags); + if (err) + goto out_freeiov; + err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr, + &user_msg->msg_controllen); + if (err) + goto out_freeiov; + err = len; - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); +out_freeiov: + if (iov != iovstack) + sock_kfree_s(sock->sk, iov, iov_size); +out_put: + sockfd_put(sock); out: - if(err < 0) - return err; - return len; + return err; } diff --git a/net/compat.c b/net/compat.c index be5d936dc423..d99ab9695893 100644 --- a/net/compat.c +++ b/net/compat.c @@ -91,20 +91,11 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, } else kern_msg->msg_name = NULL; - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - tot_len = iov_from_user_compat_to_kern(kern_iov, (struct compat_iovec __user *)kern_msg->msg_iov, kern_msg->msg_iovlen); if(tot_len >= 0) kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); return tot_len; } -- cgit v1.2.3 From dc9352a42c6de578c932313448257cf246b2b75f Mon Sep 17 00:00:00 2001 From: Markus Lidel Date: Tue, 9 Aug 2005 14:30:57 -0700 Subject: [PATCH] I2O: added pci_request_regions() before using the controller Added pci_request_regions() before using the controller to avoid duplicate usage of the I2O controller when the dpt_i2o driver and I2O subsystem is loaded at the same time. Signed-off-by: Markus Lidel Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 7a60fd7be8ad..66c03e882570 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -32,6 +32,8 @@ #include #include "core.h" +#define OSM_DESCRIPTION "I2O-subsystem" + /* PCI device id table for all I2O controllers */ static struct pci_device_id __devinitdata i2o_pci_ids[] = { {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, @@ -66,6 +68,8 @@ static void i2o_pci_free(struct i2o_controller *c) if (c->base.virt) iounmap(c->base.virt); + + pci_release_regions(c->pdev); } /** @@ -84,6 +88,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) struct device *dev = &pdev->dev; int i; + if (pci_request_regions(pdev, OSM_DESCRIPTION)) { + printk(KERN_ERR "%s: device already claimed\n", c->name); + return -ENODEV; + } + for (i = 0; i < 6; i++) { /* Skip I/O spaces */ if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { @@ -138,6 +147,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) c->base.virt = ioremap_nocache(c->base.phys, c->base.len); if (!c->base.virt) { printk(KERN_ERR "%s: Unable to map controller.\n", c->name); + i2o_pci_free(c); return -ENOMEM; } -- cgit v1.2.3 From e179d8b0552e2fdb45c6022c589af945f8cbecbe Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 9 Aug 2005 17:48:54 -0700 Subject: [PATCH] dvb: lgdt330x frontend: trivial text cleanups Two trivial text changes in Kconfig and lgdt330x.c Signed-off-by: Michael Krufky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/Kconfig | 2 +- drivers/media/dvb/frontends/lgdt330x.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index e83256d0fd14..a50a41f6f79d 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -188,7 +188,7 @@ config DVB_BCM3510 support this frontend. config DVB_LGDT330X - tristate "LGDT3302 or LGDT3303 based (DViCO FusionHDTV Gold)" + tristate "LG Electronics LGDT3302/LGDT3303 based" depends on DVB_CORE help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index c48e7c11d708..e1c71afad214 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -772,7 +772,7 @@ error: static struct dvb_frontend_ops lgdt3302_ops = { .info = { - .name= "LG Electronics LGDT3302/LGDT3303 VSB/QAM Frontend", + .name= "LG Electronics LGDT3302 VSB/QAM Frontend", .type = FE_ATSC, .frequency_min= 54000000, .frequency_max= 858000000, -- cgit v1.2.3 From aeb3f76350e78aba90653b563de6677b442d21d6 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 9 Aug 2005 17:48:54 -0700 Subject: [PATCH] DVB: lgdt330x frontend: some bug fixes & add lgdt3303 support This patch removes the tda9887 stuff from lgdt330x.c. It's experimental code which wasn't supposed to leak out and we don't want it in 2.6.13. Signed-off-by: Michael Krufky Acked-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb/frontends/lgdt330x.c | 35 ---------------------------------- 1 file changed, 35 deletions(-) diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index e1c71afad214..1f1cd7a8d500 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -172,38 +172,6 @@ static int lgdt330x_SwReset(struct lgdt330x_state* state) } } -#ifdef MUTE_TDA9887 -static int i2c_write_ntsc_demod (struct lgdt330x_state* state, u8 buf[2]) -{ - struct i2c_msg msg = - { .addr = 0x43, - .flags = 0, - .buf = buf, - .len = 2 }; - int err; - - if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - return 0; -} - -static void fiddle_with_ntsc_if_demod(struct lgdt330x_state* state) -{ - // Experimental code - u8 buf0[] = {0x00, 0x20}; - u8 buf1[] = {0x01, 0x00}; - u8 buf2[] = {0x02, 0x00}; - - i2c_write_ntsc_demod(state, buf0); - i2c_write_ntsc_demod(state, buf1); - i2c_write_ntsc_demod(state, buf2); -} -#endif static int lgdt330x_init(struct dvb_frontend* fe) { @@ -267,9 +235,6 @@ static int lgdt330x_init(struct dvb_frontend* fe) chip_name = "LGDT3303"; err = i2c_write_demod_bytes(state, lgdt3303_init_data, sizeof(lgdt3303_init_data)); -#ifdef MUTE_TDA9887 - fiddle_with_ntsc_if_demod(state); -#endif break; default: chip_name = "undefined"; -- cgit v1.2.3 From 86b3786078d63242d3194ffc58ae8dae1d1bbef3 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 9 Aug 2005 19:59:21 -0700 Subject: [PATCH] Fix ide-disk.c oops caused by hwif == NULL 1. Move hwif_to_node to ide.h 2. Use hwif_to_node in ide-disk.c Signed-off-by: Christoph Lameter Signed-off-by: Linus Torvalds --- drivers/ide/ide-disk.c | 2 +- drivers/ide/ide-probe.c | 9 --------- include/linux/ide.h | 6 ++++++ 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index f9c1acb4ed6a..c9d3a00a3c0c 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1220,7 +1220,7 @@ static int ide_disk_probe(struct device *dev) goto failed; g = alloc_disk_node(1 << PARTN_BITS, - pcibus_to_node(drive->hwif->pci_dev->bus)); + hwif_to_node(drive->hwif)); if (!g) goto out_free_idkp; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 94daf40ae323..c1128ae5cd2f 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -960,15 +960,6 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) } #endif /* MAX_HWIFS > 1 */ -static inline int hwif_to_node(ide_hwif_t *hwif) -{ - if (hwif->pci_dev) - return pcibus_to_node(hwif->pci_dev->bus); - else - /* Add ways to determine the node of other busses here */ - return -1; -} - /* * init request queue */ diff --git a/include/linux/ide.h b/include/linux/ide.h index 92129078d4f3..a6dbb51ecd7b 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1501,4 +1501,10 @@ extern struct bus_type ide_bus_type; #define ide_id_has_flush_cache_ext(id) \ (((id)->cfs_enable_2 & 0x2400) == 0x2400) +static inline int hwif_to_node(ide_hwif_t *hwif) +{ + struct pci_dev *dev = hwif->pci_dev; + return dev ? pcibus_to_node(dev->bus) : -1; +} + #endif /* _IDE_H */ -- cgit v1.2.3 From 3c4ee4e2520775896efc6ab850c4c27971fbcf2a Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 10 Aug 2005 14:41:45 +0100 Subject: [ARM SMP] Only enable V6K instructions on V6 MP core CPUs Signed-off-by: Russell King --- arch/arm/lib/bitops.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index 2036ff15bda9..64a988c1ad44 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -1,4 +1,6 @@ -#if __LINUX_ARM_ARCH__ >= 6 +#include + +#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_MPCORE) .macro bitop, instr mov r2, #1 and r3, r0, #7 @ Get bit offset -- cgit v1.2.3 From b876386ee47e3ac9375a36e9107b8bd32e0599fc Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 10 Aug 2005 14:52:52 +0100 Subject: [ARM SMP] Clear the exclusive monitor on ARMv6 CPUs on context switch Ensure that the exclusive monitor is cleared on context switch with ARMv6 CPUs. Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 39a6c1b0b9a3..7152bfbee581 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -533,6 +533,13 @@ ENTRY(__switch_to) ldr r3, [r2, #TI_TP_VALUE] stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack ldr r6, [r2, #TI_CPU_DOMAIN]! +#if __LINUX_ARM_ARCH__ >= 6 +#ifdef CONFIG_CPU_MPCORE + clrex +#else + strex r3, r4, [ip] @ Clear exclusive monitor +#endif +#endif #if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) mra r4, r5, acc0 stmia ip, {r4, r5} -- cgit v1.2.3 From 1b9749e7f15bf2db19f5d201f88401c7517910b7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 10 Aug 2005 16:15:32 +0100 Subject: [ARM] Use #defined constants for manipulating v6 hardware PTE bits Signed-off-by: Russell King --- arch/arm/mm/proc-v6.S | 20 +++++++------------- include/asm-arm/pgtable.h | 12 +++++++++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 352db98ee269..75e65522c8d2 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -111,12 +111,6 @@ ENTRY(cpu_v6_switch_mm) mcr p15, 0, r1, c13, c0, 1 @ set context ID mov pc, lr -#define nG (1 << 11) -#define APX (1 << 9) -#define AP1 (1 << 5) -#define AP0 (1 << 4) -#define XN (1 << 0) - /* * cpu_v6_set_pte(ptep, pte) * @@ -141,22 +135,22 @@ ENTRY(cpu_v6_set_pte) bic r2, r1, #0x00000ff0 bic r2, r2, #0x00000003 - orr r2, r2, #AP0 | 2 + orr r2, r2, #PTE_EXT_AP0 | 2 tst r1, #L_PTE_WRITE tstne r1, #L_PTE_DIRTY - orreq r2, r2, #APX + orreq r2, r2, #PTE_EXT_APX tst r1, #L_PTE_USER - orrne r2, r2, #AP1 | nG - tstne r2, #APX - bicne r2, r2, #APX | AP0 + orrne r2, r2, #PTE_EXT_AP1 | PTE_EXT_NG + tstne r2, #PTE_EXT_APX + bicne r2, r2, #PTE_EXT_APX | PTE_EXT_AP0 tst r1, #L_PTE_YOUNG - biceq r2, r2, #APX | AP1 | AP0 + biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK @ tst r1, #L_PTE_EXEC -@ orreq r2, r2, #XN +@ orreq r2, r2, #PTE_EXT_XN tst r1, #L_PTE_PRESENT moveq r2, #0 diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index a9892eb42a23..8bd4c0faf230 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -188,12 +188,18 @@ extern void __pgd_error(const char *file, int line, unsigned long val); /* * - extended small page/tiny page */ +#define PTE_EXT_XN (1 << 0) /* v6 */ #define PTE_EXT_AP_MASK (3 << 4) +#define PTE_EXT_AP0 (1 << 4) +#define PTE_EXT_AP1 (2 << 4) #define PTE_EXT_AP_UNO_SRO (0 << 4) -#define PTE_EXT_AP_UNO_SRW (1 << 4) -#define PTE_EXT_AP_URO_SRW (2 << 4) -#define PTE_EXT_AP_URW_SRW (3 << 4) +#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0) +#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1) +#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0) #define PTE_EXT_TEX(x) ((x) << 6) /* v5 */ +#define PTE_EXT_APX (1 << 9) /* v6 */ +#define PTE_EXT_SHARED (1 << 10) /* v6 */ +#define PTE_EXT_NG (1 << 11) /* v6 */ /* * - small page -- cgit v1.2.3 From 6626a7076d39f0a18156cdd97d4e2cbef91ad701 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 10 Aug 2005 16:18:35 +0100 Subject: [ARM] Control v6 'global' bit via Linux PTE entries Unfortunately, we can't use the "user" bit in the page tables to control whether a page table entry is "global" or "asid" specific, since the vector page is mapped as "user" accessible but is not process specific. Therefore, give direct control of the ARMv6 "nG" (not global) bit to the mm layers. Signed-off-by: Russell King --- arch/arm/mm/mm-armv.c | 17 ++++++++++++++--- arch/arm/mm/proc-v6.S | 4 ++-- include/asm-arm/pgtable.h | 2 ++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index e33fe4229d05..3c655c54e231 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -383,6 +383,7 @@ static void __init build_mem_type_table(void) { struct cachepolicy *cp; unsigned int cr = get_cr(); + unsigned int user_pgprot; int cpu_arch = cpu_architecture(); int i; @@ -408,6 +409,9 @@ static void __init build_mem_type_table(void) } } + cp = &cache_policies[cachepolicy]; + user_pgprot = cp->pte; + /* * ARMv6 and above have extended page tables. */ @@ -426,11 +430,18 @@ static void __init build_mem_type_table(void) mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; + /* + * Mark the device area as "shared device" + */ mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE; mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED; - } - cp = &cache_policies[cachepolicy]; + /* + * User pages need to be mapped with the ASID + * (iow, non-global) + */ + user_pgprot |= L_PTE_ASID; + } if (cpu_arch >= CPU_ARCH_ARMv5) { mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE; @@ -448,7 +459,7 @@ static void __init build_mem_type_table(void) for (i = 0; i < 16; i++) { unsigned long v = pgprot_val(protection_map[i]); - v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | cp->pte; + v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; protection_map[i] = __pgprot(v); } diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 75e65522c8d2..3429ddcf65d1 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -133,7 +133,7 @@ ENTRY(cpu_v6_switch_mm) ENTRY(cpu_v6_set_pte) str r1, [r0], #-2048 @ linux version - bic r2, r1, #0x00000ff0 + bic r2, r1, #0x000007f0 bic r2, r2, #0x00000003 orr r2, r2, #PTE_EXT_AP0 | 2 @@ -142,7 +142,7 @@ ENTRY(cpu_v6_set_pte) orreq r2, r2, #PTE_EXT_APX tst r1, #L_PTE_USER - orrne r2, r2, #PTE_EXT_AP1 | PTE_EXT_NG + orrne r2, r2, #PTE_EXT_AP1 tstne r2, #PTE_EXT_APX bicne r2, r2, #PTE_EXT_APX | PTE_EXT_AP0 diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index 8bd4c0faf230..478c49b56e18 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -230,6 +230,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val); #define L_PTE_WRITE (1 << 5) #define L_PTE_EXEC (1 << 6) #define L_PTE_DIRTY (1 << 7) +#define L_PTE_SHARED (1 << 10) /* shared between CPUs (v6) */ +#define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */ #ifndef __ASSEMBLY__ -- cgit v1.2.3 From 8d3722667762af1490db18ba927386d3be89a32b Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 10 Aug 2005 16:45:13 +0100 Subject: [PATCH] ARM: 2846/1: proper handling of CKEN for pxafb Patch from Nicolas Pitre Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- drivers/video/pxafb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 16e37a535d85..30112816420c 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -717,6 +717,9 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); + /* enable LCD controller clock */ + pxa_set_cken(CKEN16_LCD, 1); + /* Sequence from 11.7.10 */ LCCR3 = fbi->reg_lccr3; LCCR2 = fbi->reg_lccr2; @@ -750,6 +753,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) schedule_timeout(20 * HZ / 1000); remove_wait_queue(&fbi->ctrlr_wait, &wait); + + /* disable LCD controller clock */ + pxa_set_cken(CKEN16_LCD, 0); } /* @@ -1299,8 +1305,6 @@ int __init pxafb_probe(struct device *dev) ret = -ENOMEM; goto failed; } - /* enable LCD controller clock */ - pxa_set_cken(CKEN16_LCD, 1); ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi); if (ret) { -- cgit v1.2.3 From c59d071d4a32e1c45cac6d47f5b59ec36a9a997b Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 10 Aug 2005 16:45:14 +0100 Subject: [PATCH] ARM: 2847/1: S3C24XX - Documentation for USB OHCI host Patch from Ben Dooks Documentation for the in-built OHCI host controller and the support for it in Linux. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- Documentation/arm/Samsung-S3C24XX/USB-Host.txt | 93 ++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 Documentation/arm/Samsung-S3C24XX/USB-Host.txt diff --git a/Documentation/arm/Samsung-S3C24XX/USB-Host.txt b/Documentation/arm/Samsung-S3C24XX/USB-Host.txt new file mode 100644 index 000000000000..b93b68e2b143 --- /dev/null +++ b/Documentation/arm/Samsung-S3C24XX/USB-Host.txt @@ -0,0 +1,93 @@ + S3C24XX USB Host support + ======================== + + + +Introduction +------------ + + This document details the S3C2410/S3C2440 in-built OHCI USB host support. + +Configuration +------------- + + Enable at least the following kernel options: + + menuconfig: + + Device Drivers ---> + USB support ---> + <*> Support for Host-side USB + <*> OHCI HCD support + + + .config: + CONFIG_USB + CONFIG_USB_OHCI_HCD + + + Once these options are configured, the standard set of USB device + drivers can be configured and used. + + +Board Support +------------- + + The driver attaches to a platform device, which will need to be + added by the board specific support file in linux/arch/arm/mach-s3c2410, + such as mach-bast.c or mach-smdk2410.c + + The platform device's platform_data field is only needed if the + board implements extra power control or over-current monitoring. + + The OHCI driver does not ensure the state of the S3C2410's MISCCTRL + register, so if both ports are to be used for the host, then it is + the board support file's responsibility to ensure that the second + port is configured to be connected to the OHCI core. + + +Platform Data +------------- + + See linux/include/asm-arm/arch-s3c2410/usb-control.h for the + descriptions of the platform device data. An implementation + can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c . + + The `struct s3c2410_hcd_info` contains a pair of functions + that get called to enable over-current detection, and to + control the port power status. + + The ports are numbered 0 and 1. + + power_control: + + Called to enable or disable the power on the port. + + enable_oc: + + Called to enable or disable the over-current monitoring. + This should claim or release the resources being used to + check the power condition on the port, such as an IRQ. + + report_oc: + + The OHCI driver fills this field in for the over-current code + to call when there is a change to the over-current state on + an port. The ports argument is a bitmask of 1 bit per port, + with bit X being 1 for an over-current on port X. + + The function s3c2410_usb_report_oc() has been provided to + ensure this is called correctly. + + port[x]: + + This is struct describes each port, 0 or 1. The platform driver + should set the flags field of each port to S3C_HCDFLG_USED if + the port is enabled. + + + +Document Author +--------------- + +Ben Dooks, (c) 2005 Simtec Electronics -- cgit v1.2.3 From 484ae6bd9506488089c33784eff35b190fa80e03 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 10 Aug 2005 16:45:14 +0100 Subject: [PATCH] ARM: 2849/1: S3C24XX - USB host update (2848/1) Patch from Ben Dooks Rename the s3c2410_report_oc() to s3c2410_usb_report_oc() as this is an usb specific function. Change port power on the usb-simtec implementation to only power up the output if both are set, as per the usb 1.1 specification Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/usb-simtec.c | 18 +++++++++++++----- include/asm-arm/arch-s3c2410/usb-control.h | 3 ++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c index 7f2b61362976..f021fd82be52 100644 --- a/arch/arm/mach-s3c2410/usb-simtec.c +++ b/arch/arm/mach-s3c2410/usb-simtec.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/usb-simtec.c * - * Copyright (c) 2004 Simtec Electronics + * Copyright (c) 2004,2005 Simtec Electronics * Ben Dooks * * http://www.simtec.co.uk/products/EB2410ITX/ @@ -14,6 +14,8 @@ * Modifications: * 14-Sep-2004 BJD Created * 18-Oct-2004 BJD Cleanups, and added code to report OC cleared + * 09-Aug-2005 BJD Renamed s3c2410_report_oc to s3c2410_usb_report_oc + * 09-Aug-2005 BJD Ports powered only if both are enabled */ #define DEBUG @@ -47,13 +49,19 @@ * designed boards. */ +static unsigned int power_state[2]; + static void usb_simtec_powercontrol(int port, int to) { pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to); - if (port == 1) - s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1); + power_state[port] = to; + + if (power_state[0] && power_state[1]) + s3c2410_gpio_setpin(S3C2410_GPB4, 0); + else + s3c2410_gpio_setpin(S3C2410_GPB4, 1); } static irqreturn_t @@ -63,10 +71,10 @@ usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs) if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) { pr_debug("usb_simtec: over-current irq (oc detected)\n"); - s3c2410_report_oc(info, 3); + s3c2410_usb_report_oc(info, 3); } else { pr_debug("usb_simtec: over-current irq (oc cleared)\n"); - s3c2410_report_oc(info, 0); + s3c2410_usb_report_oc(info, 0); } return IRQ_HANDLED; diff --git a/include/asm-arm/arch-s3c2410/usb-control.h b/include/asm-arm/arch-s3c2410/usb-control.h index 1cc85a096b23..bd43b566db3e 100644 --- a/include/asm-arm/arch-s3c2410/usb-control.h +++ b/include/asm-arm/arch-s3c2410/usb-control.h @@ -12,6 +12,7 @@ * Changelog: * 11-Sep-2004 BJD Created file * 21-Sep-2004 BJD Updated port info + * 09-Aug-2005 BJD Renamed s3c2410_report_oc s3c2410_usb_report_oc */ #ifndef __ASM_ARCH_USBCONTROL_H @@ -35,7 +36,7 @@ struct s3c2410_hcd_info { void (*report_oc)(struct s3c2410_hcd_info *, int ports); }; -static void inline s3c2410_report_oc(struct s3c2410_hcd_info *info, int ports) +static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports) { if (info->report_oc != NULL) { (info->report_oc)(info, ports); -- cgit v1.2.3 From fae009847c9ea3d668bbee21ce1d76764eca5039 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 7 Aug 2005 14:53:40 +0900 Subject: [PATCH] sata: fix sata_sx4 dma_prep to not use sg->length sata_sx4 directly references sg->length to calculate total_len in pdc20621_dma_prep(). This is incorrect as dma_map_sg() could have merged multiple sg's into one and, in such case, sg->length doesn't reflect true size of the entry. This patch makes it use sg_dma_len(sg). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/sata_sx4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 140cea05de3f..efd7d7a61135 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -468,7 +468,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc) for (i = 0; i < last; i++) { buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i])); buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i])); - total_len += sg[i].length; + total_len += sg_dma_len(&sg[i]); } buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); sgt_len = idx * 4; -- cgit v1.2.3 From 42517438f9c1011a03e49a542cba32ac5a80dd8e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 10 Aug 2005 13:38:27 -0400 Subject: libata: fix EH-related lockup by properly cleaning EH command list Yet another hack due to the fact that libata is the only user of SCSI's ->eh_strategy_handler() hook. --- drivers/scsi/libata-scsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 794fb559efb0..6a75ec2187fd 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -385,6 +385,7 @@ int ata_scsi_error(struct Scsi_Host *host) * appropriate place */ host->host_failed--; + INIT_LIST_HEAD(&host->eh_cmd_q); DPRINTK("EXIT\n"); return 0; -- cgit v1.2.3 From c0438174e8272d23fe43a5d3f23d777f5b412e87 Mon Sep 17 00:00:00 2001 From: Ralf Baechle DL5RB Date: Wed, 10 Aug 2005 10:03:20 -0700 Subject: [PATCH] 6pack persistence fix Fix the p-persistence CSMA algorithm which in simplex mode was starting with a slottime delay before doing anything else as if there was carrier collision resulting in bad performance on simplex links. Signed-off-by: Ralf Baechle DL5RB Acked-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/hamradio/6pack.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index e44f8e9055ef..f9e3be96963c 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -130,12 +130,11 @@ struct sixpack { #define AX25_6PACK_HEADER_LEN 0 -static void sp_start_tx_timer(struct sixpack *); static void sixpack_decode(struct sixpack *, unsigned char[], int); static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); /* - * perform the persistence/slottime algorithm for CSMA access. If the + * Perform the persistence/slottime algorithm for CSMA access. If the * persistence check was successful, write the data to the serial driver. * Note that in case of DAMA operation, the data is not sent here. */ @@ -143,7 +142,7 @@ static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char); static void sp_xmit_on_air(unsigned long channel) { struct sixpack *sp = (struct sixpack *) channel; - int actual; + int actual, when = sp->slottime; static unsigned char random; random = random * 17 + 41; @@ -159,20 +158,10 @@ static void sp_xmit_on_air(unsigned long channel) sp->tty->driver->write(sp->tty, &sp->led_state, 1); sp->status2 = 0; } else - sp_start_tx_timer(sp); + mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100); } /* ----> 6pack timer interrupt handler and friends. <---- */ -static void sp_start_tx_timer(struct sixpack *sp) -{ - int when = sp->slottime; - - del_timer(&sp->tx_t); - sp->tx_t.data = (unsigned long) sp; - sp->tx_t.function = sp_xmit_on_air; - sp->tx_t.expires = jiffies + ((when + 1) * HZ) / 100; - add_timer(&sp->tx_t); -} /* Encapsulate one AX.25 frame and stuff into a TTY queue. */ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) @@ -243,8 +232,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len) sp->xleft = count; sp->xhead = sp->xbuff; sp->status2 = count; - if (sp->duplex == 0) - sp_start_tx_timer(sp); + sp_xmit_on_air((unsigned long)sp); } return; -- cgit v1.2.3 From 22d0def9d09111513f5a8d38583210620f97d710 Mon Sep 17 00:00:00 2001 From: Alexander Nyberg Date: Wed, 10 Aug 2005 10:11:36 -0700 Subject: [PATCH] ns558 list handling fix Need to use list_for_entry_safe(), as we're removing items during the traversal. list_for_each_entry() uses the first ptr also as an iterator, if you kfree() it slab takes it, might poison it and then you try to use it to iterate to the next object in list. Cc: Vojtech Pavlik Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/gameport/ns558.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index 1ab5f2dc8a2a..70f051894a3c 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c @@ -275,9 +275,9 @@ static int __init ns558_init(void) static void __exit ns558_exit(void) { - struct ns558 *ns558; + struct ns558 *ns558, *safe; - list_for_each_entry(ns558, &ns558_list, node) { + list_for_each_entry_safe(ns558, safe, &ns558_list, node) { gameport_unregister_port(ns558->gameport); release_region(ns558->io & ~(ns558->size - 1), ns558->size); kfree(ns558); -- cgit v1.2.3 From e62b8b2bc73b2433239a2ac394c2fafd50c43d9e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 10 Aug 2005 11:12:09 +0200 Subject: [PATCH] ppc64: Fix Fan control for new PowerMac G5 2.7GHz machines The workaround for broken device-tree that prevents fan control from working on recent G5 models need to be "enabled" for machines with revision 0x37 of the bridge in addition to machines with revision 0x35. Signed-off-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/prom_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index e248a7950aeb..dbbe6c79d8da 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -1803,7 +1803,7 @@ static void __init fixup_device_tree(void) if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) == PROM_ERROR) return; - if (u3_rev != 0x35) + if (u3_rev != 0x35 && u3_rev != 0x37) return; /* does it need fixup ? */ if (prom_getproplen(i2c, "interrupts") > 0) -- cgit v1.2.3 From 3462b925414a146d4c2252de97d20f89218d1ffb Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 11 Jul 2005 14:19:35 +0200 Subject: [PATCH] wbsd version bump Even though the changes are minor for the next release an increasing version number simplifies my support issues. Signed-off-by: Pierre Ossman Signed-off-by: Linus Torvalds --- drivers/mmc/wbsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 8b487ed1069c..974f2f36bdbe 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -42,7 +42,7 @@ #include "wbsd.h" #define DRIVER_NAME "wbsd" -#define DRIVER_VERSION "1.2" +#define DRIVER_VERSION "1.3" #ifdef CONFIG_MMC_DEBUG #define DBG(x...) \ -- cgit v1.2.3 From 001ab02a8c04f0b4dc773c474da698ad7405ae68 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 10 Aug 2005 11:32:57 -0700 Subject: [DECNET]: Use sk_stream_error function rather than DECnet's own Signed-off-by: Steven Whitehouse Signed-off-by: David S. Miller --- net/decnet/af_decnet.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 96a02800cd28..acdd18e6adb2 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -1876,15 +1876,6 @@ static inline unsigned int dn_current_mss(struct sock *sk, int flags) return mss_now; } -static int dn_error(struct sock *sk, int flags, int err) -{ - if (err == -EPIPE) - err = sock_error(sk) ? : -EPIPE; - if (err == -EPIPE && !(flags & MSG_NOSIGNAL)) - send_sig(SIGPIPE, current, 0); - return err; -} - static int dn_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size) { @@ -2045,7 +2036,7 @@ out: return sent ? sent : err; out_err: - err = dn_error(sk, flags, err); + err = sk_stream_error(sk, flags, err); release_sock(sk); return err; } -- cgit v1.2.3 From 606867443764edac5a2c542f2fa0a12ef7a7c7fd Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 10 Aug 2005 11:29:15 -0700 Subject: [PATCH] remove name length check in a workqueue We have a chek in there to make sure that the name won't overflow task_struct.comm[], but it's triggering for scsi with lots of HBAs, only scsi is using single-threaded workqueues which don't append the "/%d" anyway. All too hard. Just kill the BUG_ON. Cc: Ingo Molnar Signed-off-by: Andrew Morton [ kthread_create() uses vsnprintf() and limits the thing, so no actual overflow can actually happen regardless ] Signed-off-by: Linus Torvalds --- kernel/workqueue.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 259cf55da3c9..c7e36d4a70ca 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -308,8 +308,6 @@ struct workqueue_struct *__create_workqueue(const char *name, struct workqueue_struct *wq; struct task_struct *p; - BUG_ON(strlen(name) > 10); - wq = kmalloc(sizeof(*wq), GFP_KERNEL); if (!wq) return NULL; -- cgit v1.2.3 From b5da623ae9be680ea59f268eeb339f0acb2d88c4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 10 Aug 2005 18:32:36 -0700 Subject: [TCP]: Adjust {p,f}ackets_out correctly in tcp_retransmit_skb() Well I've only found one potential cause for the assertion failure in tcp_mark_head_lost. First of all, this can only occur if cnt > 1 since tp->packets_out is never zero here. If it did hit zero we'd have much bigger problems. So cnt is equal to fackets_out - reordering. Normally fackets_out is less than packets_out. The only reason I've found that might cause fackets_out to exceed packets_out is if tcp_fragment is called from tcp_retransmit_skb with a TSO skb and the current MSS is greater than the MSS stored in the TSO skb. This might occur as the result of an expiring dst entry. In that case, packets_out may decrease (line 1380-1381 in tcp_output.c). However, fackets_out is unchanged which means that it may in fact exceed packets_out. Previously tcp_retrans_try_collapse was the only place where packets_out can go down and it takes care of this by decrementing fackets_out. So we should make sure that fackets_out is reduced by an appropriate amount here as well. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7d076f0db100..3ed6fc15815b 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1370,15 +1370,21 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) if (skb->len > cur_mss) { int old_factor = tcp_skb_pcount(skb); - int new_factor; + int diff; if (tcp_fragment(sk, skb, cur_mss, cur_mss)) return -ENOMEM; /* We'll try again later. */ /* New SKB created, account for it. */ - new_factor = tcp_skb_pcount(skb); - tp->packets_out -= old_factor - new_factor; - tp->packets_out += tcp_skb_pcount(skb->next); + diff = old_factor - tcp_skb_pcount(skb) - + tcp_skb_pcount(skb->next); + tp->packets_out -= diff; + + if (diff > 0) { + tp->fackets_out -= diff; + if ((int)tp->fackets_out < 0) + tp->fackets_out = 0; + } } /* Collapse two adjacent packets if worthwhile and we can. */ -- cgit v1.2.3 From 7d69fa6266770eeb6317eddd46b64456e8a515bf Mon Sep 17 00:00:00 2001 From: Johannes Stezenbach Date: Thu, 11 Aug 2005 11:54:24 +0200 Subject: [PATCH] Fix DVB URL Signed-off-by: Johannes Stezenbach Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5fd00c075053..3b38d6ab06cf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -784,7 +784,7 @@ DVB SUBSYSTEM AND DRIVERS P: LinuxTV.org Project M: linux-dvb-maintainer@linuxtv.org L: linux-dvb@linuxtv.org (subscription required) -W: http://linuxtv.org/developer/dvb.xml +W: http://linuxtv.org/ S: Supported EATA-DMA SCSI DRIVER -- cgit v1.2.3 From a0d3bea3cf6c7c1b53a46432bd490b5dc784ca42 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 11 Aug 2005 16:05:50 -0700 Subject: [NET]: Make skb->protocol __be16 There are many instances of skb->protocol = htons(ETH_P_*); skb->protocol = __constant_htons(ETH_P_*); and skb->protocol = *_type_trans(...); Most of *_type_trans() are already endian-annotated, so, let's shift attention on other warnings. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 0061c9470482..948527e42a60 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -255,7 +255,7 @@ struct sk_buff { nohdr:1; /* 3 bits spare */ __u8 pkt_type; - __u16 protocol; + __be16 protocol; void (*destructor)(struct sk_buff *skb); #ifdef CONFIG_NETFILTER -- cgit v1.2.3 From 11513128bb66b0b09d5d0df069b58afdb01752a2 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Thu, 11 Aug 2005 19:23:04 -0700 Subject: [NETPOLL]: rx_flags bugfix Initialize npinfo->rx_flags. The way it stands now, this will have random garbage, and so will incur a locking penalty even when an rx_hook isn't registered and we are not active in the netpoll polling code. Signed-off-by: Jeff Moyer Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index c327c9edadc5..895f3efc65aa 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -639,6 +639,7 @@ int netpoll_setup(struct netpoll *np) if (!npinfo) goto release; + npinfo->rx_flags = 0; npinfo->rx_np = NULL; npinfo->poll_lock = SPIN_LOCK_UNLOCKED; npinfo->poll_owner = -1; -- cgit v1.2.3 From a636e1357911afdea7c8344ee65f78d36caf3c16 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Thu, 11 Aug 2005 19:23:50 -0700 Subject: [NETPOLL]: deadlock bugfix This fixes an obvious deadlock in the netpoll code. netpoll_rx takes the npinfo->rx_lock. netpoll_rx is also the only caller of arp_reply (through __netpoll_rx). As such, it is not necessary to take this lock. Signed-off-by: Jeff Moyer Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 895f3efc65aa..b9d9da082af2 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -353,11 +353,8 @@ static void arp_reply(struct sk_buff *skb) struct sk_buff *send_skb; struct netpoll *np = NULL; - spin_lock_irqsave(&npinfo->rx_lock, flags); if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev) np = npinfo->rx_np; - spin_unlock_irqrestore(&npinfo->rx_lock, flags); - if (!np) return; -- cgit v1.2.3 From 6b0b31572985c2e64f7216c798766302fb782281 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:24:33 -0700 Subject: [NETPOLL]: e1000 netpoll tweak Suggested by Steven Rostedt, matches his patch included in e100. Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5e5d2c3c7ce4..b82fd15d0891 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3789,6 +3789,7 @@ e1000_netpoll(struct net_device *netdev) struct e1000_adapter *adapter = netdev_priv(netdev); disable_irq(adapter->pdev->irq); e1000_intr(adapter->pdev->irq, netdev, NULL); + e1000_clean_tx_irq(adapter); enable_irq(adapter->pdev->irq); } #endif -- cgit v1.2.3 From f0d3459d0722782c7d9d0e35a1ed0815e75fcde5 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:25:11 -0700 Subject: [NETPOLL]: netpoll_send_skb simplify Minor netpoll_send_skb restructuring Restructure to avoid confusing goto and move some bits out of the retry loop. Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index b9d9da082af2..59ed186e4f46 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -248,14 +248,14 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) int status; struct netpoll_info *npinfo; -repeat: - if(!np || !np->dev || !netif_running(np->dev)) { + if (!np || !np->dev || !netif_running(np->dev)) { __kfree_skb(skb); return; } - /* avoid recursion */ npinfo = np->dev->npinfo; + + /* avoid recursion */ if (npinfo->poll_owner == smp_processor_id() || np->dev->xmit_lock_owner == smp_processor_id()) { if (np->drop) @@ -265,29 +265,31 @@ repeat: return; } - spin_lock(&np->dev->xmit_lock); - np->dev->xmit_lock_owner = smp_processor_id(); + while (1) { + spin_lock(&np->dev->xmit_lock); + np->dev->xmit_lock_owner = smp_processor_id(); - /* - * network drivers do not expect to be called if the queue is - * stopped. - */ - if (netif_queue_stopped(np->dev)) { + /* + * network drivers do not expect to be called if the queue is + * stopped. + */ + if (netif_queue_stopped(np->dev)) { + np->dev->xmit_lock_owner = -1; + spin_unlock(&np->dev->xmit_lock); + netpoll_poll(np); + continue; + } + + status = np->dev->hard_start_xmit(skb, np->dev); np->dev->xmit_lock_owner = -1; spin_unlock(&np->dev->xmit_lock); - netpoll_poll(np); - goto repeat; - } - - status = np->dev->hard_start_xmit(skb, np->dev); - np->dev->xmit_lock_owner = -1; - spin_unlock(&np->dev->xmit_lock); + /* success */ + if(!status) + return; - /* transmit busy */ - if(status) { + /* transmit busy */ netpoll_poll(np); - goto repeat; } } -- cgit v1.2.3 From 0db1d6fc1ea051af49ebe03c503d23996a7c5bbb Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:25:54 -0700 Subject: [NETPOLL]: add retry timeout Add limited retry logic to netpoll_send_skb Each time we attempt to send, decrement our per-device retry counter. On every successful send, we reset the counter. We delay 50us between attempts with up to 20000 retries for a total of 1 second. After we've exhausted our retries, subsequent failed attempts will try only once until reset by success. Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- include/linux/netpoll.h | 1 + net/core/netpoll.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index bcd0ac33f592..be68d94b03d5 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -26,6 +26,7 @@ struct netpoll { struct netpoll_info { spinlock_t poll_lock; int poll_owner; + int tries; int rx_flags; spinlock_t rx_lock; struct netpoll *rx_np; /* netpoll that registered an rx_hook */ diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 59ed186e4f46..d09affdbad3c 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -33,6 +33,7 @@ #define MAX_UDP_CHUNK 1460 #define MAX_SKBS 32 #define MAX_QUEUE_DEPTH (MAX_SKBS / 2) +#define MAX_RETRIES 20000 static DEFINE_SPINLOCK(skb_list_lock); static int nr_skbs; @@ -265,7 +266,8 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) return; } - while (1) { + do { + npinfo->tries--; spin_lock(&np->dev->xmit_lock); np->dev->xmit_lock_owner = smp_processor_id(); @@ -277,6 +279,7 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) np->dev->xmit_lock_owner = -1; spin_unlock(&np->dev->xmit_lock); netpoll_poll(np); + udelay(50); continue; } @@ -285,12 +288,15 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) spin_unlock(&np->dev->xmit_lock); /* success */ - if(!status) + if(!status) { + npinfo->tries = MAX_RETRIES; /* reset */ return; + } /* transmit busy */ netpoll_poll(np); - } + udelay(50); + } while (npinfo->tries > 0); } void netpoll_send_udp(struct netpoll *np, const char *msg, int len) @@ -642,6 +648,7 @@ int netpoll_setup(struct netpoll *np) npinfo->rx_np = NULL; npinfo->poll_lock = SPIN_LOCK_UNLOCKED; npinfo->poll_owner = -1; + npinfo->tries = MAX_RETRIES; npinfo->rx_lock = SPIN_LOCK_UNLOCKED; } else npinfo = ndev->npinfo; -- cgit v1.2.3 From 2652076507b662fc88ba16c27b59c7bdd9ccd956 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 11 Aug 2005 19:26:42 -0700 Subject: [NETPOLL]: pre-fill skb pool we could do one thing (see the patch below): i think it would be useful to fill up the netlogging skb queue straight at initialization time. Especially if netpoll is used for dumping alone, the system might not be in a situation to fill up the queue at the point of crash, so better be a bit more prepared and keep the pipeline filled. [ I've modified this to be called earlier - mpm ] Signed-off-by: Ingo Molnar Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index d09affdbad3c..c02a08da6d42 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -725,6 +725,10 @@ int netpoll_setup(struct netpoll *np) npinfo->rx_np = np; spin_unlock_irqrestore(&npinfo->rx_lock, flags); } + + /* fill up the skb queue */ + refill_skbs(); + /* last thing to do is link it to the net device structure */ ndev->npinfo = npinfo; -- cgit v1.2.3 From 53fb95d3c14290fd6ee808b221e35493f096246f Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:27:43 -0700 Subject: [NETPOLL]: fix initialization/NAPI race This fixes a race during initialization with the NAPI softirq processing by using an RCU approach. This race was discovered when refill_skbs() was added to the setup code. Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- include/linux/netpoll.h | 19 +++++++++++++------ net/core/dev.c | 9 +++++---- net/core/netpoll.c | 3 +++ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index be68d94b03d5..5ade54a78dbb 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -9,6 +9,7 @@ #include #include +#include #include struct netpoll; @@ -61,25 +62,31 @@ static inline int netpoll_rx(struct sk_buff *skb) return ret; } -static inline void netpoll_poll_lock(struct net_device *dev) +static inline void *netpoll_poll_lock(struct net_device *dev) { + rcu_read_lock(); /* deal with race on ->npinfo */ if (dev->npinfo) { spin_lock(&dev->npinfo->poll_lock); dev->npinfo->poll_owner = smp_processor_id(); + return dev->npinfo; } + return NULL; } -static inline void netpoll_poll_unlock(struct net_device *dev) +static inline void netpoll_poll_unlock(void *have) { - if (dev->npinfo) { - dev->npinfo->poll_owner = -1; - spin_unlock(&dev->npinfo->poll_lock); + struct netpoll_info *npi = have; + + if (npi) { + npi->poll_owner = -1; + spin_unlock(&npi->poll_lock); } + rcu_read_unlock(); } #else #define netpoll_rx(a) 0 -#define netpoll_poll_lock(a) +#define netpoll_poll_lock(a) 0 #define netpoll_poll_unlock(a) #endif diff --git a/net/core/dev.c b/net/core/dev.c index 52a3bf7ae177..faf59b02c4bf 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1696,7 +1696,8 @@ static void net_rx_action(struct softirq_action *h) struct softnet_data *queue = &__get_cpu_var(softnet_data); unsigned long start_time = jiffies; int budget = netdev_budget; - + void *have; + local_irq_disable(); while (!list_empty(&queue->poll_list)) { @@ -1709,10 +1710,10 @@ static void net_rx_action(struct softirq_action *h) dev = list_entry(queue->poll_list.next, struct net_device, poll_list); - netpoll_poll_lock(dev); + have = netpoll_poll_lock(dev); if (dev->quota <= 0 || dev->poll(dev, &budget)) { - netpoll_poll_unlock(dev); + netpoll_poll_unlock(have); local_irq_disable(); list_del(&dev->poll_list); list_add_tail(&dev->poll_list, &queue->poll_list); @@ -1721,7 +1722,7 @@ static void net_rx_action(struct softirq_action *h) else dev->quota = dev->weight; } else { - netpoll_poll_unlock(dev); + netpoll_poll_unlock(have); dev_put(dev); local_irq_disable(); } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index c02a08da6d42..996787bca17f 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -732,6 +732,9 @@ int netpoll_setup(struct netpoll *np) /* last thing to do is link it to the net device structure */ ndev->npinfo = npinfo; + /* avoid racing with NAPI reading npinfo */ + synchronize_rcu(); + return 0; release: -- cgit v1.2.3 From d7b9dfc8ea43936e6e8eec3040dcf4f110563868 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:28:05 -0700 Subject: [NETPOLL]: remove unused variable Remove unused variable Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 996787bca17f..a1a9a7abff50 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -357,7 +357,6 @@ static void arp_reply(struct sk_buff *skb) unsigned char *arp_ptr; int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; u32 sip, tip; - unsigned long flags; struct sk_buff *send_skb; struct netpoll *np = NULL; -- cgit v1.2.3 From 349188f66da2fd88f8cb2407763051d8e136c9aa Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 11 Aug 2005 22:26:25 -0600 Subject: [PATCH] x86_64: Fix apicid versus cpu# confusion. Oops. I knew I didn't have the physical versus logical cpu identifiers right when I generated that patch. It's not nearly as bad as I feared at the time though. Signed-off-by: Eric W. Biederman Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/smpboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 6e4807d64d46..b15761ff4101 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -334,7 +334,7 @@ static void __cpuinit tsc_sync_wait(void) { if (notscsync || !cpu_has_tsc) return; - sync_tsc(boot_cpu_id); + sync_tsc(0); } static __init int notscsync_setup(char *s) -- cgit v1.2.3 From 2da5bf80f754e28cc153362e5ed1edaa9740897a Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Fri, 12 Aug 2005 11:46:22 -0700 Subject: [PATCH] w1: more debug level decrease. Do not spam syslog each 10 seconds when there is nothing on the wire. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/w1/w1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 8a9c42822502..0bbf029b1ef1 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -593,7 +593,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb) * Return 0 - device(s) present, 1 - no devices present. */ if (w1_reset_bus(dev)) { - dev_info(&dev->dev, "No devices present on the wire.\n"); + dev_dbg(&dev->dev, "No devices present on the wire.\n"); break; } -- cgit v1.2.3 From 4bb82551e165f887448f6f61055d7bcd90aefa2a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 13 Aug 2005 14:22:59 -0700 Subject: Fix up mmap of /dev/kmem This leaves the issue of whether we should deprecate the whole thing (or if we should check the whole mmap range, for that matter) open. Just do the minimal fix for now. --- drivers/char/mem.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 42187381506b..850a78c9c4bc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -261,7 +261,11 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) static int mmap_kmem(struct file * file, struct vm_area_struct * vma) { - unsigned long long val; + unsigned long pfn; + + /* Turn a kernel-virtual address into a physical page frame */ + pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; + /* * RED-PEN: on some architectures there is more mapped memory * than available in mem_map which pfn_valid checks @@ -269,10 +273,10 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) * * RED-PEN: vmalloc is not supported right now. */ - if (!pfn_valid(vma->vm_pgoff)) + if (!pfn_valid(pfn)) return -EIO; - val = (u64)vma->vm_pgoff << PAGE_SHIFT; - vma->vm_pgoff = __pa(val) >> PAGE_SHIFT; + + vma->vm_pgoff = pfn; return mmap_mem(file, vma); } -- cgit v1.2.3 From f73bc8cae3481adc4188a5f34a89025c10133b0a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 13 Aug 2005 20:28:06 +0300 Subject: [PATCH] sh: Make _syscall6() do the right thing. There was a rather silly and embarrassing typo in the sh _syscall6(). For the syscall ABI we have the trapa value specified as 0x10 + number of arguments, this was being set incorrectly in the _syscall6() case which ended up causing some problems for users. Signed-off-by: Paul Mundt Signed-off-by: Linus Torvalds --- include/asm-sh/unistd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h index 245447081f0d..4e7701d6d23c 100644 --- a/include/asm-sh/unistd.h +++ b/include/asm-sh/unistd.h @@ -406,7 +406,7 @@ register long __sc6 __asm__ ("r6") = (long) arg3; \ register long __sc7 __asm__ ("r7") = (long) arg4; \ register long __sc0 __asm__ ("r0") = (long) arg5; \ register long __sc1 __asm__ ("r1") = (long) arg6; \ -__asm__ __volatile__ ("trapa #0x15" \ +__asm__ __volatile__ ("trapa #0x16" \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \ "r" (__sc3), "r" (__sc1) \ -- cgit v1.2.3 From 1b0a74d1c002320d5488333dd9c72126af1aab02 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sat, 13 Aug 2005 13:15:34 +0200 Subject: [PATCH] Fix error handling in reiserfs Initialize key object ID in inode so that we don't try to remove the inode when we fail on some checks even before we manage to allocate something. Signed-off-by: Jan Kara Signed-off-by: Linus Torvalds --- fs/reiserfs/namei.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index a20bbc1642dc..3549067c42d9 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -593,6 +593,9 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode) */ inode->i_uid = current->fsuid; inode->i_mode = mode; + /* Make inode invalid - just in case we are going to drop it before + * the initialization happens */ + INODE_PKEY(inode)->k_objectid = 0; if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; -- cgit v1.2.3 From d024709deb4997aced6140a62e8ee82b10666c5f Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 14 Aug 2005 16:55:23 -0500 Subject: [PATCH] CIFS: Fix missing entries in search results Fix missing entries in search results when very long file names and more than 50 (or so) of such long search entries in the directory. FindNext could send corrupt last byte of resume name when resume key was a few hundred bytes long file name or longer. Fixes Samba Bug # 2932 Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifssmb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 3c628bf667a5..0db0b313d715 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2602,6 +2602,9 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, if(name_len < PATH_MAX) { memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len); byte_count += name_len; + /* 14 byte parm len above enough for 2 byte null terminator */ + pSMB->ResumeFileName[name_len] = 0; + pSMB->ResumeFileName[name_len+1] = 0; } else { rc = -EINVAL; goto FNext2_err_exit; -- cgit v1.2.3 From 27876d02b30aa34bb1ad35b81ccc40c174282f31 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 14 Aug 2005 16:55:23 -0500 Subject: [PATCH] CIFS: Fix path name conversion for long filenames Fix path name conversion for long filenames when mapchars mount option was specified at mount time. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 6 ++++++ fs/cifs/misc.c | 1 + 2 files changed, 7 insertions(+) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index dab4774ee7bb..3196d4c4eed3 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,9 @@ +Version 1.35 +------------ +Add writepage performance improvements. Fix path name conversions +for long filenames on mounts which were done with "mapchars" mount option +specified. + Version 1.34 ------------ Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 072b4ee8c53e..20ae4153f791 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -611,6 +611,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, src_char = source[i]; switch (src_char) { case 0: + target[j] = 0; goto ctoUCS_out; case ':': target[j] = cpu_to_le16(UNI_COLON); -- cgit v1.2.3 From b4b08e581fac8e0ba9ae348bdc13246c9798c99e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 14 Aug 2005 15:43:39 -0700 Subject: Revert "dc395x: Fix support for highmem" It introduces a repeatable oops in the driver, which is a bigger problem than the patch tries to solve. From the original description: Author: Jamie Lenehan Date: Thu Mar 3 14:41:40 2005 +0200 [PATCH] dc395x: Fix support for highmem From: Guennadi Liakhovetski Removes the page_to_virt and maps sg lists dynamically. This makes the driver work with highmem pages. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Jamie Lenehan Signed-off-by: James Bottomley Signed-off-by: Guennadi Liakhovetski Signed-off-by: Linus Torvalds --- drivers/scsi/dc395x.c | 48 +++++++++++++----------------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 929170dcd3cb..600ba1202864 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -183,7 +183,7 @@ * cross a page boundy. */ #define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY) -#define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY) + struct SGentry { u32 address; /* bus! address */ @@ -235,7 +235,6 @@ struct ScsiReqBlk { u8 sg_count; /* No of HW sg entries for this request */ u8 sg_index; /* Index of HW sg entry for this request */ u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ - void **virt_map; unsigned char *virt_addr; /* Virtual address of current transfer position */ /* @@ -1022,14 +1021,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, reqlen, cmd->request_buffer, cmd->use_sg, srb->sg_count); + srb->virt_addr = page_address(sl->page); for (i = 0; i < srb->sg_count; i++) { - u32 seglen = (u32)sg_dma_len(sl + i); - sgp[i].address = (u32)sg_dma_address(sl + i); + u32 busaddr = (u32)sg_dma_address(&sl[i]); + u32 seglen = (u32)sl[i].length; + sgp[i].address = busaddr; sgp[i].length = seglen; srb->total_xfer_length += seglen; - srb->virt_map[i] = kmap(sl[i].page); } - srb->virt_addr = srb->virt_map[0]; sgp += srb->sg_count - 1; /* @@ -1976,7 +1975,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) int segment = cmd->use_sg; u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ struct SGentry *psge = srb->segment_x + srb->sg_index; - void **virt = srb->virt_map; dprintkdbg(DBG_0, "sg_update_list: Transfered %i of %i bytes, %i remain\n", @@ -2016,16 +2014,16 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) /* We have to walk the scatterlist to find it */ sg = (struct scatterlist *)cmd->request_buffer; - idx = 0; while (segment--) { unsigned long mask = ~((unsigned long)sg->length - 1) & PAGE_MASK; if ((sg_dma_address(sg) & mask) == (psge->address & mask)) { - srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK); + srb->virt_addr = (page_address(sg->page) + + psge->address - + (psge->address & PAGE_MASK)); return; } ++sg; - ++idx; } dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n"); @@ -2151,7 +2149,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, DC395x_read32(acb, TRM_S1040_DMA_CXCNT)); } /* - * calculate all the residue data that not yet transfered + * calculate all the residue data that not yet tranfered * SCSI transfer counter + left in SCSI FIFO data * * .....TRM_S1040_SCSI_COUNTER (24bits) @@ -3269,7 +3267,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) struct scsi_cmnd *cmd = srb->cmd; enum dma_data_direction dir = cmd->sc_data_direction; if (cmd->use_sg && dir != PCI_DMA_NONE) { - int i; /* unmap DC395x SG list */ dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n", srb->sg_bus_addr, SEGMENTX_LEN); @@ -3279,8 +3276,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n", cmd->use_sg, cmd->request_buffer); /* unmap the sg segments */ - for (i = 0; i < srb->sg_count; i++) - kunmap(virt_to_page(srb->virt_map[i])); pci_unmap_sg(acb->dev, (struct scatterlist *)cmd->request_buffer, cmd->use_sg, dir); @@ -3327,7 +3322,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (cmd->use_sg) { struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; - ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset); + ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset); } else { ptr = (struct ScsiInqData *)(cmd->request_buffer); } @@ -4262,9 +4257,8 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN; for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) - kfree(acb->srb_array[i].segment_x); - - vfree(acb->srb_array[0].virt_map); + if (acb->srb_array[i].segment_x) + kfree(acb->srb_array[i].segment_x); } @@ -4280,12 +4274,9 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) int srb_idx = 0; unsigned i = 0; struct SGentry *ptr; - void **virt_array; - for (i = 0; i < DC395x_MAX_SRB_CNT; i++) { + for (i = 0; i < DC395x_MAX_SRB_CNT; i++) acb->srb_array[i].segment_x = NULL; - acb->srb_array[i].virt_map = NULL; - } dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); while (pages--) { @@ -4306,19 +4297,6 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) ptr + (i * DC395x_MAX_SG_LISTENTRY); else dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); - - virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*)); - - if (!virt_array) { - adapter_sg_tables_free(acb); - return 1; - } - - for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) { - acb->srb_array[i].virt_map = virt_array; - virt_array += DC395x_MAX_SG_LISTENTRY; - } - return 0; } -- cgit v1.2.3 From 2ba84684e8cf6f980e4e95a2300f53a505eb794e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 14 Aug 2005 18:21:30 -0700 Subject: Revert PCIBIOS_MIN_IO changes for 2.6.13 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commits 71db63acff69618b3d9d3114bd061938150e146b [PATCH] increase PCIBIOS_MIN_IO on x86 and 0b2bfb4e7ff61f286676867c3508569bea6fbf7a ACPI: increase PCIBIOS_MIN_IO on x86 since Lukas Sandströ reports that this breaks his on-board nvidia audio. We should re-visit this later. For now we revert the change Signed-off-by: Linus Torvalds --- drivers/acpi/motherboard.c | 2 +- include/asm-i386/pci.h | 4 +++- include/asm-x86_64/pci.h | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index 2934475d67d6..61ea70742d49 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -43,7 +43,7 @@ ACPI_MODULE_NAME ("acpi_motherboard") */ #define IS_RESERVED_ADDR(base, len) \ (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \ - && ((base) + (len) > 0x1000)) + && ((base) + (len) > PCIBIOS_MIN_IO)) /* * Clearing the flag (IORESOURCE_BUSY) allows drivers to use diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h index 2cbab30734d6..78c85985aee3 100644 --- a/include/asm-i386/pci.h +++ b/include/asm-i386/pci.h @@ -18,9 +18,11 @@ extern unsigned int pcibios_assign_all_busses(void); #define pcibios_scan_all_fns(a, b) 0 extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x4000 +#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM (pci_mem_start) +#define PCIBIOS_MIN_CARDBUS_IO 0x4000 + void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h index 9c4527eb55e2..eeb3088a1c9e 100644 --- a/include/asm-x86_64/pci.h +++ b/include/asm-x86_64/pci.h @@ -22,9 +22,11 @@ extern unsigned int pcibios_assign_all_busses(void); extern int no_iommu, force_iommu; extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x4000 +#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM (pci_mem_start) +#define PCIBIOS_MIN_CARDBUS_IO 0x4000 + void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value); -- cgit v1.2.3 From f241be74b803dcf9d70c9978292946370654320f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 14 Aug 2005 19:08:45 -0700 Subject: [PATCH] ieee80211: Fix frame control pver mask IEEE 802.11 frame control has two bits reserved for protocol version. IEEE80211_FCTL_VERS was not used anywhere, but I would assume it was supposed to be a mask for the protocol field and as such, it should be 0x0003, not 0x0002. This matches with WLAN_FC_PVER definition in hostap. Signed-off-by: Jouni Malinen Signed-off-by: Jeff Garzik --- include/net/ieee80211.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index 1cf7ca0b6182..11524c9b659a 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -104,7 +104,7 @@ struct eapol { #define MAX_FRAG_THRESHOLD 2346U /* Frame control field constants */ -#define IEEE80211_FCTL_VERS 0x0002 +#define IEEE80211_FCTL_VERS 0x0003 #define IEEE80211_FCTL_FTYPE 0x000c #define IEEE80211_FCTL_STYPE 0x00f0 #define IEEE80211_FCTL_TODS 0x0100 -- cgit v1.2.3