Commit cfc615f2 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-pnp.bkbits.net/pnp-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents a0b18907 7ee49b42
......@@ -563,7 +563,7 @@ $(sort $(vmlinux-objs)) arch/$(ARCH)/kernel/vmlinux.lds.s: $(SUBDIRS) ;
# Handle descending into subdirectories listed in $(SUBDIRS)
.PHONY: $(SUBDIRS)
$(SUBDIRS): prepare-all
$(SUBDIRS): prepare-all scripts
$(Q)$(MAKE) $(build)=$@
# Things we need to do before we recursively start building the kernel
......
......@@ -608,6 +608,7 @@ create_iface(struct device_node *np, struct device *dev)
}
#endif /* POLLED_MODE */
pmac_low_i2c_unlock(np);
dev_set_drvdata(dev, iface);
for (i=0; i<nchan; i++) {
......@@ -645,7 +646,6 @@ create_iface(struct device_node *np, struct device *dev)
printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n",
np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps);
pmac_low_i2c_unlock(np);
return 0;
}
......
/* $Id: capifunc.c,v 1.48 2004/01/11 19:20:54 armin Exp $
/* $Id: capifunc.c,v 1.57 2004/03/20 18:18:03 armin Exp $
*
* ISDN interface module for Eicon active cards DIVA.
* CAPI Interface common functions
......@@ -18,6 +18,7 @@
#include "divacapi.h"
#include "divasync.h"
#include "capifunc.h"
#include "dlist.h"
#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
......@@ -39,9 +40,9 @@ extern word CapiRegister(word);
extern word api_put(APPL *, CAPI_MSG *);
static diva_os_spin_lock_t api_lock;
static diva_os_spin_lock_t ll_lock;
static diva_card *cards;
static LIST_HEAD(cards);
static dword notify_handle;
static void DIRequest(ENTITY * e);
static DESCRIPTOR MAdapter;
......@@ -57,6 +58,11 @@ static u16 diva_send_message(struct capi_ctr *,
diva_os_message_buffer_s *);
extern void diva_os_set_controller_struct(struct capi_ctr *);
/*
* include queue functions
*/
#include "dlist.c"
extern void DIVA_DIDD_Read(DESCRIPTOR *, int);
/*
......@@ -152,26 +158,15 @@ byte UnMapController(byte MappedController)
static int find_free_id(void)
{
int num = 0;
diva_card *p;
diva_os_spin_lock_magic_t old_irql;
DIVA_CAPI_ADAPTER *a;
diva_os_enter_spin_lock(&ll_lock, &old_irql, "find free id");
while (num < 100) {
num++;
p = cards;
while (p) {
if (p->Id == num)
while (num < MAX_DESCRIPTORS) {
a = &adapter[num];
if (!a->Id)
break;
p = p->next;
}
if(!p) {
diva_os_leave_spin_lock(&ll_lock, &old_irql,
"find free id");
return (num);
}
num++;
}
diva_os_leave_spin_lock(&ll_lock, &old_irql, "find free id");
return (999);
return(num + 1);
}
/*
......@@ -179,21 +174,17 @@ static int find_free_id(void)
*/
static diva_card *find_card_by_ctrl(word controller)
{
diva_card *p;
diva_os_spin_lock_magic_t old_irql;
diva_os_enter_spin_lock(&ll_lock, &old_irql, "find card ctrl");
p = cards;
struct list_head *tmp;
diva_card *card;
while (p) {
if (ControllerMap[p->Id] == controller) {
diva_os_leave_spin_lock(&ll_lock, &old_irql,
"find card ctrl");
return p;
list_for_each(tmp, &cards) {
card = list_entry(tmp, diva_card, list);
if (ControllerMap[card->Id] == controller) {
if (card->remove_in_progress)
card = NULL;
return(card);
}
p = p->next;
}
diva_os_leave_spin_lock(&ll_lock, &old_irql, "find card ctrl");
return (diva_card *) 0;
}
......@@ -358,28 +349,18 @@ void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...)
/*
* cleanup adapter
*/
static void clean_adapter(int id)
static void clean_adapter(int id, diva_entity_queue_t* free_mem_q)
{
DIVA_CAPI_ADAPTER *a;
#if IMPLEMENT_LINE_INTERCONNECT2
int i, k;
#endif /* IMPLEMENT_LINE_INTERCONNECT2 */
a = &adapter[id];
#if IMPLEMENT_LINE_INTERCONNECT
if (a->li_pri) {
if (a->li_config.pri)
diva_os_free(0, a->li_config.pri);
} else {
if (a->li_config.bri)
diva_os_free(0, a->li_config.bri);
}
#endif /* IMPLEMENT_LINE_INTERCONNECT */
#if IMPLEMENT_LINE_INTERCONNECT2
k = li_total_channels - a->li_channels;
if (k == 0) {
diva_os_free(0, li_config_table);
if (li_config_table) {
diva_q_add_tail(free_mem_q, (diva_entity_link_t*)li_config_table);
li_config_table = NULL;
}
} else {
if (a->li_base < k) {
memmove(&li_config_table[a->li_base],
......@@ -401,9 +382,8 @@ static void clean_adapter(int id)
if (adapter[i].request)
adapter[i].li_base -= a->li_channels;
}
#endif /* IMPLEMENT_LINE_INTERCONNECT2 */
if (a->plci)
diva_os_free(0, a->plci);
diva_q_add_tail(free_mem_q, (diva_entity_link_t*)a->plci);
memset(a, 0x00, sizeof(DIVA_CAPI_ADAPTER));
while ((max_adapter != 0) && !adapter[max_adapter - 1].request)
......@@ -411,67 +391,87 @@ static void clean_adapter(int id)
}
/*
* remove cards
* remove a card, but ensures consistent state of LI tables
* in the time adapter is removed
*/
static void DIVA_EXIT_FUNCTION divacapi_remove_cards(void)
static void divacapi_remove_card(DESCRIPTOR * d)
{
diva_card *last;
diva_card *card;
struct list_head *tmp;
diva_card *card = NULL;
diva_entity_queue_t free_mem_q;
diva_entity_link_t* link;
diva_os_spin_lock_magic_t old_irql;
diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove cards");
card = cards;
diva_q_init (&free_mem_q);
while (card) {
/*
* Set "remove in progress flag".
* Ensures that there is no call from sendf to CAPI in
* the time CAPI controller is about to be removed.
*/
diva_os_enter_spin_lock(&api_lock, &old_irql, "remove card");
list_for_each(tmp, &cards) {
card = list_entry(tmp, diva_card, list);
if (card->d.request == d->request) {
card->remove_in_progress = 1;
list_del(tmp);
break;
}
}
diva_os_leave_spin_lock(&api_lock, &old_irql, "remove card");
if (card) {
/*
* Detach CAPI. Sendf cannot call to CAPI any more.
* After detach no call to send_message() is done too.
*/
detach_capi_ctr(&card->capi_ctrl);
clean_adapter(card->Id - 1);
DBG_TRC(("adapter remove, max_adapter=%d", max_adapter));
card = card->next;
/*
* Now get API lock (to ensure stable state of LI tables)
* and update the adapter map/LI table.
*/
diva_os_enter_spin_lock(&api_lock, &old_irql, "remove card");
clean_adapter(card->Id - 1, &free_mem_q);
DBG_TRC(("DelAdapterMap (%d) -> (%d)",
ControllerMap[card->Id], card->Id))
ControllerMap[card->Id] = 0;
DBG_TRC(("adapter remove, max_adapter=%d",
max_adapter));
diva_os_leave_spin_lock(&api_lock, &old_irql, "remove card");
/* After releasing the lock, we can free the memory */
diva_os_free (0, card);
}
card = cards;
while (card) {
last = card;
card = card->next;
diva_os_free(0, last);
/* free queued memory areas */
while ((link = diva_q_get_head(&free_mem_q))) {
diva_q_remove(&free_mem_q, link);
diva_os_free(0, link);
}
diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove cards");
}
/*
* remove a card
* remove cards
*/
static void divacapi_remove_card(DESCRIPTOR * d)
static void DIVA_EXIT_FUNCTION divacapi_remove_cards(void)
{
diva_card *last;
DESCRIPTOR d;
struct list_head *tmp;
diva_card *card;
diva_os_spin_lock_magic_t old_irql;
diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove card");
last = card = cards;
while (card) {
if (card->d.request == d->request) {
detach_capi_ctr(&card->capi_ctrl);
clean_adapter(card->Id - 1);
DBG_TRC(
("DelAdapterMap (%d) -> (%d)",
ControllerMap[card->Id], card->Id))
ControllerMap[card->Id] = 0;
DBG_TRC(
("adapter remove, max_adapter=%d",
max_adapter));
if (card == last)
cards = card->next;
else
last->next = card->next;
diva_os_free(0, card);
break;
}
last = card;
card = card->next;
rescan:
diva_os_enter_spin_lock(&api_lock, &old_irql, "remove cards");
list_for_each(tmp, &cards) {
card = list_entry(tmp, diva_card, list);
diva_os_leave_spin_lock(&api_lock, &old_irql, "remove cards");
d.request = card->d.request;
divacapi_remove_card(&d);
goto rescan;
}
diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove card");
diva_os_leave_spin_lock(&api_lock, &old_irql, "remove cards");
}
/*
......@@ -500,10 +500,9 @@ static int diva_add_card(DESCRIPTOR * d)
DIVA_CAPI_ADAPTER *a = NULL;
IDI_SYNC_REQ sync_req;
char serial[16];
#if IMPLEMENT_LINE_INTERCONNECT2
void* mem_to_free;
LI_CONFIG *new_li_config_table;
int j;
#endif /* IMPLEMENT_LINE_INTERCONNECT2 */
if (!(card = (diva_card *) diva_os_malloc(0, sizeof(diva_card)))) {
DBG_ERR(("diva_add_card: failed to allocate card struct."))
......@@ -529,7 +528,11 @@ static int diva_add_card(DESCRIPTOR * d)
diva_os_free(0, card);
return (0);
}
diva_os_enter_spin_lock(&api_lock, &old_irql, "find id");
card->Id = find_free_id();
diva_os_leave_spin_lock(&api_lock, &old_irql, "find id");
strlcpy(ctrl->manu, M_COMPANY, sizeof(ctrl->manu));
ctrl->version.majorversion = 2;
ctrl->version.minorversion = 0;
......@@ -600,9 +603,7 @@ static int diva_add_card(DESCRIPTOR * d)
#if IMPLEMENT_DTMF
a->profile.Global_Options |= 0x8;
#endif /* IMPLEMENT_DTMF */
#if (IMPLEMENT_LINE_INTERCONNECT || IMPLEMENT_LINE_INTERCONNECT2)
a->profile.Global_Options |= 0x80;
#endif /* (IMPLEMENT_LINE_INTERCONNECT || IMPLEMENT_LINE_INTERCONNECT2) */
a->profile.Global_Options |= 0x80; /* Line Interconnect */
#if IMPLEMENT_ECHO_CANCELLER
a->profile.Global_Options |= 0x100;
#endif /* IMPLEMENT_ECHO_CANCELLER */
......@@ -620,25 +621,6 @@ static int diva_add_card(DESCRIPTOR * d)
a->manufacturer_features = 0;
}
#if IMPLEMENT_LINE_INTERCONNECT
a->li_pri = (a->profile.Channels > 2);
if (a->li_pri) {
if (!(a->li_config.pri = (LI_CONFIG_PRI *) diva_os_malloc(0, sizeof(LI_CONFIG_PRI)))) {
DBG_ERR(("diva_add_card: failed alloc li_config.pri struct."))
memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
return (0);
}
memset(a->li_config.pri, 0, sizeof(LI_CONFIG_PRI));
} else
if (!(a->li_config.bri = (LI_CONFIG_BRI *) diva_os_malloc(0, sizeof(LI_CONFIG_BRI)))) {
DBG_ERR(("diva_add_card: failed alloc li_config.bri struct."))
memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
return (0);
}
memset(a->li_config.bri, 0, sizeof(LI_CONFIG_BRI));
}
#endif /* IMPLEMENT_LINE_INTERCONNECT */
#if IMPLEMENT_LINE_INTERCONNECT2
a->li_pri = (a->profile.Channels > 2);
a->li_channels = a->li_pri ? MIXER_CHANNELS_PRI : MIXER_CHANNELS_BRI;
a->li_base = 0;
......@@ -654,6 +636,10 @@ static int diva_add_card(DESCRIPTOR * d)
memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
return (0);
}
/* Prevent access to line interconnect table in process update */
diva_os_enter_spin_lock(&api_lock, &old_irql, "add card");
j = 0;
for (i = 0; i < k; i++) {
if ((i >= a->li_base) && (i < a->li_base + a->li_channels))
......@@ -694,25 +680,26 @@ static int diva_add_card(DESCRIPTOR * d)
}
li_total_channels = k;
if (li_config_table != NULL)
diva_os_free(0, li_config_table);
mem_to_free = li_config_table;
li_config_table = new_li_config_table;
for (i = card->Id; i < max_adapter; i++) {
if (adapter[i].request)
adapter[i].li_base += a->li_channels;
}
#endif /* IMPLEMENT_LINE_INTERCONNECT2 */
if (a == &adapter[max_adapter])
max_adapter++;
diva_os_enter_spin_lock(&ll_lock, &old_irql, "add card");
card->next = cards;
cards = card;
diva_os_leave_spin_lock(&ll_lock, &old_irql, "add card");
list_add(&(card->list), &cards);
AutomaticLaw(a);
diva_os_leave_spin_lock(&api_lock, &old_irql, "add card");
if (mem_to_free) {
diva_os_free (0, mem_to_free);
}
i = 0;
while (i++ < 30) {
if (a->automatic_law > 3)
......@@ -863,6 +850,7 @@ static void diva_release_appl(struct capi_ctr *ctrl, __u16 appl)
{
diva_os_spin_lock_magic_t old_irql;
APPL *this = &application[appl - 1];
void *mem_to_free = NULL;
DBG_TRC(("application %d(%d) cleanup", this->Id, appl))
......@@ -874,13 +862,15 @@ static void diva_release_appl(struct capi_ctr *ctrl, __u16 appl)
diva_os_enter_spin_lock(&api_lock, &old_irql, "release_appl");
if (this->Id) {
CapiRelease(this->Id);
if (this->DataNCCI)
diva_os_free(0, this->DataNCCI);
mem_to_free = this->DataNCCI;
this->DataNCCI = NULL;
this->Id = 0;
}
diva_os_leave_spin_lock(&api_lock, &old_irql, "release_appl");
if (mem_to_free)
diva_os_free(0, mem_to_free);
}
/*
......@@ -906,6 +896,11 @@ static u16 diva_send_message(struct capi_ctr *ctrl,
}
DBG_PRV1(("Write - appl = %d, cmd = 0x%x", this->Id, command))
if (card->remove_in_progress) {
DBG_ERR(("CAPI_SEND_MSG - remove in progress!"))
return CAPI_REGOSRESOURCEERR;
}
if (!this->Id) {
return CAPI_ILLAPPNR;
}
......@@ -1162,12 +1157,31 @@ static void remove_main_structs(void)
diva_os_free(0, mapped_msg);
}
/*
* api_remove_start
*/
static void do_api_remove_start(void)
{
diva_os_spin_lock_magic_t old_irql;
int ret = 1, count = 100;
do {
diva_os_enter_spin_lock(&api_lock, &old_irql, "api remove start");
ret = api_remove_start();
diva_os_leave_spin_lock(&api_lock, &old_irql, "api remove start");
diva_os_sleep(10);
} while (ret && count--);
if (ret)
DBG_ERR(("could not remove signaling ID's"))
}
/*
* init
*/
int DIVA_INIT_FUNCTION init_capifunc(void)
{
diva_os_initialize_spin_lock(&ll_lock, "capifunc");
diva_os_initialize_spin_lock(&api_lock, "capifunc");
memset(ControllerMap, 0, MAX_DESCRIPTORS + 1);
max_adapter = 0;
......@@ -1175,12 +1189,16 @@ int DIVA_INIT_FUNCTION init_capifunc(void)
if (!init_main_structs()) {
DBG_ERR(("init: failed to init main structs."))
diva_os_destroy_spin_lock(&api_lock, "capifunc");
return (0);
}
if (!divacapi_connect_didd()) {
DBG_ERR(("init: failed to connect to DIDD."))
do_api_remove_start();
divacapi_remove_cards();
remove_main_structs();
diva_os_destroy_spin_lock(&api_lock, "capifunc");
return (0);
}
......@@ -1192,21 +1210,9 @@ int DIVA_INIT_FUNCTION init_capifunc(void)
*/
void DIVA_EXIT_FUNCTION finit_capifunc(void)
{
int count = 100;
word ret = 1;
while (ret && count--) {
ret = api_remove_start();
diva_os_sleep(10);
}
if (ret)
DBG_ERR(("could not remove signaling ID's"))
do_api_remove_start();
divacapi_disconnect_didd();
divacapi_remove_cards();
remove_main_structs();
diva_os_destroy_spin_lock(&api_lock, "capifunc");
diva_os_destroy_spin_lock(&ll_lock, "capifunc");
}
/* $Id: capifunc.h,v 1.10 2003/08/25 10:06:37 schindler Exp $
/* $Id: capifunc.h,v 1.11 2004/03/20 17:19:58 armin Exp $
*
* ISDN interface module for Eicon active cards DIVA.
* CAPI Interface common functions
......@@ -24,8 +24,9 @@
extern char DRIVERRELEASE_CAPI[];
typedef struct _diva_card {
struct list_head list;
int remove_in_progress;
int Id;
struct _diva_card *next;
struct capi_ctr capi_ctrl;
DIVA_CAPI_ADAPTER *adapter;
DESCRIPTOR d;
......
/* $Id: divasmain.c,v 1.48 2004/02/24 17:46:28 armin Exp $
/* $Id: divasmain.c,v 1.51 2004/03/20 20:47:08 armin Exp $
*
* Low level driver for Eicon DIVA Server ISDN cards.
*
......@@ -41,7 +41,7 @@
#include "diva_dma.h"
#include "diva_pci.h"
static char *main_revision = "$Revision: 1.48 $";
static char *main_revision = "$Revision: 1.51 $";
static int major;
......@@ -69,7 +69,7 @@ extern int divasfunc_init(int dbgmask);
extern void divasfunc_exit(void);
typedef struct _diva_os_thread_dpc {
struct work_struct divas_task;
struct tasklet_struct divas_task;
struct work_struct trap_script_task;
diva_os_soft_isr_t *psoft_isr;
int card_failed;
......@@ -552,7 +552,7 @@ void diva_os_remove_irq(void *context, byte irq)
/* --------------------------------------------------------------------------
DPC framework implementation
-------------------------------------------------------------------------- */
static void diva_os_dpc_proc(void *context)
static void diva_os_dpc_proc(unsigned long context)
{
diva_os_thread_dpc_t *psoft_isr = (diva_os_thread_dpc_t *) context;
diva_os_soft_isr_t *pisr = psoft_isr->psoft_isr;
......@@ -575,7 +575,7 @@ int diva_os_initialize_soft_isr(diva_os_soft_isr_t * psoft_isr,
psoft_isr->callback_context = callback_context;
pdpc->psoft_isr = psoft_isr;
INIT_WORK(&pdpc->trap_script_task, diva_adapter_trapped, pdpc);
INIT_WORK(&pdpc->divas_task, diva_os_dpc_proc, pdpc);
tasklet_init(&pdpc->divas_task, diva_os_dpc_proc, (unsigned long)pdpc);
return (0);
}
......@@ -586,7 +586,7 @@ int diva_os_schedule_soft_isr(diva_os_soft_isr_t * psoft_isr)
diva_os_thread_dpc_t *pdpc =
(diva_os_thread_dpc_t *) psoft_isr->object;
schedule_work(&pdpc->divas_task);
tasklet_schedule(&pdpc->divas_task);
}
return (1);
......@@ -594,14 +594,22 @@ int diva_os_schedule_soft_isr(diva_os_soft_isr_t * psoft_isr)
int diva_os_cancel_soft_isr(diva_os_soft_isr_t * psoft_isr)
{
if (psoft_isr && psoft_isr->object) {
diva_os_thread_dpc_t *pdpc =
(diva_os_thread_dpc_t *) psoft_isr->object;
tasklet_kill(&pdpc->divas_task);
}
return (0);
}
void diva_os_remove_soft_isr(diva_os_soft_isr_t * psoft_isr)
{
if (psoft_isr && psoft_isr->object) {
diva_os_thread_dpc_t *pdpc =
(diva_os_thread_dpc_t *) psoft_isr->object;
void *mem;
tasklet_kill(&pdpc->divas_task);
flush_scheduled_work();
mem = psoft_isr->object;
psoft_isr->object = 0;
......
/* $Id: platform.h,v 1.35 2003/12/05 18:45:05 armin Exp $
/* $Id: platform.h,v 1.37 2004/03/20 17:44:29 armin Exp $
*
* platform.h
*
......@@ -29,6 +29,7 @@
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <asm/types.h>
#include <asm/io.h>
......@@ -332,7 +333,6 @@ diva_os_atomic_decrement(diva_os_atomic_t* pv)
*/
#define NO_CORNETN
#define IMPLEMENT_DTMF 1
#define IMPLEMENT_LINE_INTERCONNECT2 1
#define IMPLEMENT_ECHO_CANCELLER 1
#define IMPLEMENT_RTP 1
#define IMPLEMENT_T38 1
......@@ -346,7 +346,6 @@ diva_os_atomic_decrement(diva_os_atomic_t* pv)
#define IMPLEMENT_FAX_NONSTANDARD 1
#define VSWITCH_SUPPORT 1
#define IMPLEMENT_LINE_INTERCONNECT 0
#define IMPLEMENT_MARKED_OK_AFTER_FC 1
#define DIVA_IDI_RX_DMA 1
......
/*
* Creation Date: <2003/03/14 20:54:13 samuel>
* Time-stamp: <2003/03/15 18:55:53 samuel>
* Time-stamp: <2004/03/20 14:20:59 samuel>
*
* <therm_windtunnel.c>
*
* The G4 "windtunnel" has a single fan controlled by a
* DS1775 fan controller and an ADM1030 thermostat.
* The G4 "windtunnel" has a single fan controlled by an
* ADM1030 fan controller and a DS1775 thermostat.
*
* The fan controller is equipped with a temperature sensor
* which measures the case temperature. The ADM censor
* which measures the case temperature. The DS1775 sensor
* measures the CPU temperature. This driver tunes the
* behavior of the fan. It is based upon empirical observations
* of the 'AppleFan' driver under OSX.
* of the 'AppleFan' driver under Mac OS X.
*
* WARNING: This driver has only been testen on Apple's
* 1.25 MHz Dual G4 (March 03). Other machines might have
* a different thermal design. It is tuned for a CPU
* 1.25 MHz Dual G4 (March 03). It is tuned for a CPU
* temperatur around 57 C.
*
* Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se)
* Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
*
* Loosely based upon 'thermostat.c' written by Benjamin Herrenschmidt
*
......@@ -38,50 +37,37 @@
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/workqueue.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/sections.h>
MODULE_AUTHOR("Samuel Rydh <samuel@ibrium.se>");
MODULE_DESCRIPTION("Apple G4 (windtunnel) fan driver");
MODULE_LICENSE("GPL");
#include <asm/of_device.h>
#define LOG_TEMP 0 /* continously log temperature */
/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
static unsigned short normal_i2c[] = { 0x49, 0x2c, I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { 0x48, 0x4f, 0x2c, 0x2f, I2C_CLIENT_END };
static struct work_struct poll_work;
I2C_CLIENT_INSMOD;
#define I2C_DRIVERID_G4FAN 0x9001 /* fixme */
#define THERMOSTAT_CLIENT_ID 1
#define FAN_CLIENT_ID 2
struct temp_range {
u8 high; /* start the fan */
u8 low; /* stop the fan */
};
struct apple_thermal_info {
u8 id; /* implementation ID */
u8 fan_count; /* number of fans */
u8 thermostat_count; /* number of thermostats */
u8 unused[5];
struct temp_range ranges[4]; /* temperature ranges (may be [])*/
};
static int do_probe( struct i2c_adapter *adapter, int addr, int kind);
static int do_detect( struct i2c_adapter *adapter, int addr, int kind);
/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
static unsigned short normal_i2c[] = { 0x49, 0x2c, I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { 0x48, 0x4f, 0x2c, 0x2f, I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
static struct {
volatile int running;
struct completion completion;
pid_t poll_task;
struct semaphore lock;
struct of_device *of_dev;
struct i2c_client *thermostat;
struct i2c_client *fan;
int error;
struct timer_list timer;
int overheat_temp; /* 100% fan at this temp */
int overheat_hyst;
......@@ -95,37 +81,54 @@ static struct {
int r0, r1, r20, r23, r25; /* saved register */
} x;
#define T(x,y) (((x)<<8) | (y)*0x100/10 )
static struct {
int fan_down_setting;
int temp;
int fan_setting;
} fan_up_table[] = {
{ 0x0000, 11 }, /* min fan */
{ 0x3900, 8 }, /* 57.0 C */
{ 0x3a4a, 7 }, /* 58.3 C */
{ 0x3ad3, 6 }, /* 58.8 C */
{ 0x3b3c, 5 }, /* 59.2 C */
{ 0x3b94, 4 }, /* 59.6 C */
{ 0x3be3, 3 }, /* 58.9 C */
{ 0x3c29, 2 }, /* 59.2 C */
{ 0xffff, 1 } /* on fire */
};
static struct {
int temp;
int fan_setting;
} fan_down_table[] = {
{ 0x3700, 11 }, /* 55.0 C */
{ 0x374a, 6 },
{ 0x3800, 7 }, /* 56.0 C */
{ 0x3900, 8 }, /* 57.0 C */
{ 0x3a4a, 7 }, /* 58.3 C */
{ 0x3ad3, 6 }, /* 58.8 C */
{ 0x3b3c, 5 }, /* 59.2 C */
{ 0x3b94, 4 }, /* 58.9 C */
{ 0x3be3, 3 }, /* 58.9 C */
{ 0x3c29, 2 }, /* 59.2 C */
{ 0xffff, 1 }
int fan_up_setting;
} fan_table[] = {
{ 11, T(0,0), 11 }, /* min fan */
{ 11, T(55,0), 11 },
{ 6, T(55,3), 11 },
{ 7, T(56,0), 11 },
{ 8, T(57,0), 8 },
{ 7, T(58,3), 7 },
{ 6, T(58,8), 6 },
{ 5, T(59,2), 5 },
{ 4, T(59,6), 4 },
{ 3, T(59,9), 3 },
{ 2, T(60,1), 2 },
{ 1, 0xfffff, 1 } /* on fire */
};
static void
print_temp( const char *s, int temp )
{
printk("%s%d.%d C", s ? s : "", temp>>8, (temp & 255)*10/256 );
}
static ssize_t
show_cpu_temperature( struct device *dev, char *buf )
{
return sprintf(buf, "%d.%d\n", x.temp>>8, (x.temp & 255)*10/256 );
}
static ssize_t
show_case_temperature( struct device *dev, char *buf )
{
return sprintf(buf, "%d.%d\n", x.casetemp>>8, (x.casetemp & 255)*10/256 );
}
static DEVICE_ATTR(cpu_temperature, S_IRUGO, show_cpu_temperature, NULL );
static DEVICE_ATTR(case_temperature, S_IRUGO, show_case_temperature, NULL );
/************************************************************************/
/* controller thread */
/************************************************************************/
static int
write_reg( struct i2c_client *cl, int reg, int data, int len )
{
......@@ -159,37 +162,32 @@ read_reg( struct i2c_client *cl, int reg, int len )
return (len == 2)? ((unsigned int)buf[0] << 8) | buf[1] : buf[0];
}
static void
print_temp( const char *s, int temp )
{
printk("%s%d.%d C", s ? s : "", temp>>8, (temp & 255)*10/256 );
}
static void
tune_fan( int fan_setting )
{
int val = (fan_setting << 3) | 7;
x.fan_level = fan_setting;
//write_reg( x.fan, 0x24, val, 1 );
/* write_reg( x.fan, 0x24, val, 1 ); */
write_reg( x.fan, 0x25, val, 1 );
write_reg( x.fan, 0x20, 0, 1 );
print_temp("CPU-temp: ", x.temp );
if( x.casetemp )
print_temp(", Case: ", x.casetemp );
printk(" Tuning fan: %d (%02x)\n", fan_setting, val );
printk(", Fan: %d (tuned %+d)\n", 11-fan_setting, x.fan_level-fan_setting );
x.fan_level = fan_setting;
}
static void
poll_temp( void *param )
poll_temp( void )
{
int temp = read_reg( x.thermostat, 0, 2 );
int i, level, casetemp;
int temp, i, level, casetemp;
temp = read_reg( x.thermostat, 0, 2 );
/* this actually occurs when the computer is loaded */
if( temp < 0 )
goto out;
return;
casetemp = read_reg(x.fan, 0x0b, 1) << 8;
casetemp |= (read_reg(x.fan, 0x06, 1) & 0x7) << 5;
......@@ -197,37 +195,117 @@ poll_temp( void *param )
if( LOG_TEMP && x.temp != temp ) {
print_temp("CPU-temp: ", temp );
print_temp(", Case: ", casetemp );
printk(", Fan: %d\n", x.fan_level );
printk(", Fan: %d\n", 11-x.fan_level );
}
x.temp = temp;
x.casetemp = casetemp;
level = -1;
for( i=0; (temp & 0xffff) > fan_down_table[i].temp ; i++ )
for( i=0; (temp & 0xffff) > fan_table[i].temp ; i++ )
;
if( i < x.downind )
level = fan_down_table[i].fan_setting;
level = fan_table[i].fan_down_setting;
x.downind = i;
for( i=0; (temp & 0xfffe) >= fan_up_table[i+1].temp ; i++ )
for( i=0; (temp & 0xffff) >= fan_table[i+1].temp ; i++ )
;
if( x.upind < i )
level = fan_up_table[i].fan_setting;
level = fan_table[i].fan_up_setting;
x.upind = i;
if( level >= 0 )
tune_fan( level );
out:
x.timer.expires = jiffies + 8*HZ;
add_timer( &x.timer );
}
static void
setup_hardware( void )
{
int val;
/* save registers (if we unload the module) */
x.r0 = read_reg( x.fan, 0x00, 1 );
x.r1 = read_reg( x.fan, 0x01, 1 );
x.r20 = read_reg( x.fan, 0x20, 1 );
x.r23 = read_reg( x.fan, 0x23, 1 );
x.r25 = read_reg( x.fan, 0x25, 1 );
/* improve measurement resolution (convergence time 1.5s) */
if( (val=read_reg(x.thermostat, 1, 1)) >= 0 ) {
val |= 0x60;
if( write_reg( x.thermostat, 1, val, 1 ) )
printk("Failed writing config register\n");
}
/* disable interrupts and TAC input */
write_reg( x.fan, 0x01, 0x01, 1 );
/* enable filter */
write_reg( x.fan, 0x23, 0x91, 1 );
/* remote temp. controls fan */
write_reg( x.fan, 0x00, 0x95, 1 );
/* The thermostat (which besides measureing temperature controls
* has a THERM output which puts the fan on 100%) is usually
* set to kick in at 80 C (chip default). We reduce this a bit
* to be on the safe side (OSX doesn't)...
*/
if( x.overheat_temp == (80 << 8) ) {
x.overheat_temp = 65 << 8;
x.overheat_hyst = 60 << 8;
write_reg( x.thermostat, 2, x.overheat_hyst, 2 );
write_reg( x.thermostat, 3, x.overheat_temp, 2 );
print_temp("Reducing overheating limit to ", x.overheat_temp );
print_temp(" (Hyst: ", x.overheat_hyst );
printk(")\n");
}
/* set an initial fan setting */
x.downind = 0xffff;
x.upind = -1;
/* tune_fan( fan_up_table[x.upind].fan_setting ); */
device_create_file( &x.of_dev->dev, &dev_attr_cpu_temperature );
device_create_file( &x.of_dev->dev, &dev_attr_case_temperature );
}
static void
schedule_poll( unsigned long t )
restore_regs( void )
{
schedule_work(&poll_work);
device_remove_file( &x.of_dev->dev, &dev_attr_cpu_temperature );
device_remove_file( &x.of_dev->dev, &dev_attr_case_temperature );
write_reg( x.fan, 0x01, x.r1, 1 );
write_reg( x.fan, 0x20, x.r20, 1 );
write_reg( x.fan, 0x23, x.r23, 1 );
write_reg( x.fan, 0x25, x.r25, 1 );
write_reg( x.fan, 0x00, x.r0, 1 );
}
static int
control_loop( void *dummy )
{
daemonize("g4fand");
down( &x.lock );
setup_hardware();
while( x.running ) {
up( &x.lock );
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout( 8*HZ );
down( &x.lock );
poll_temp();
}
restore_regs();
up( &x.lock );
complete_and_exit( &x.completion, 0 );
}
/************************************************************************/
/* i2c probing and setup */
/************************************************************************/
......@@ -235,7 +313,20 @@ schedule_poll( unsigned long t )
static int
do_attach( struct i2c_adapter *adapter )
{
return i2c_probe( adapter, &addr_data, &do_detect );
int ret = 0;
if( strncmp(adapter->name, "uni-n", 5) )
return 0;
if( !x.running ) {
ret = i2c_probe( adapter, &addr_data, &do_probe );
if( x.thermostat && x.fan ) {
x.running = 1;
init_completion( &x.completion );
x.poll_task = kernel_thread( control_loop, NULL, SIGCHLD | CLONE_KERNEL );
}
}
return ret;
}
static int
......@@ -243,13 +334,23 @@ do_detach( struct i2c_client *client )
{
int err;
printk("do_detach: id %d\n", client->id );
if( (err=i2c_detach_client(client)) ) {
printk("failed to detach thermostat client\n");
return err;
if( (err=i2c_detach_client(client)) )
printk(KERN_ERR "failed to detach thermostat client\n");
else {
if( x.running ) {
x.running = 0;
wait_for_completion( &x.completion );
}
if( client == x.thermostat )
x.thermostat = NULL;
else if( client == x.fan )
x.fan = NULL;
else {
printk(KERN_ERR "g4fan: bad client\n");
}
kfree( client );
}
kfree( client );
return 0;
return err;
}
static struct i2c_driver g4fan_driver = {
......@@ -262,24 +363,21 @@ static struct i2c_driver g4fan_driver = {
};
static int
detect_fan( struct i2c_client *cl )
attach_fan( struct i2c_client *cl )
{
if( x.fan )
goto out;
/* check that this is an ADM1030 */
if( read_reg(cl, 0x3d, 1) != 0x30 || read_reg(cl, 0x3e, 1) != 0x41 )
goto out;
printk("ADM1030 fan controller detected at %02x\n", cl->addr );
printk("ADM1030 fan controller [@%02x]\n", cl->addr );
if( x.fan ) {
x.error |= 2;
goto out;
}
x.fan = cl;
cl->id = FAN_CLIENT_ID;
strncpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) );
strlcpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) );
if( i2c_attach_client( cl ) )
goto out;
return 0;
if( !i2c_attach_client(cl) )
x.fan = cl;
out:
if( cl != x.fan )
kfree( cl );
......@@ -287,10 +385,13 @@ detect_fan( struct i2c_client *cl )
}
static int
detect_thermostat( struct i2c_client *cl )
attach_thermostat( struct i2c_client *cl )
{
int hyst_temp, os_temp, temp;
if( x.thermostat )
goto out;
if( (temp=read_reg(cl, 0, 2)) < 0 )
goto out;
......@@ -302,44 +403,37 @@ detect_thermostat( struct i2c_client *cl )
if( hyst_temp < 0 || os_temp < 0 )
goto out;
printk("DS1775 digital thermometer detected at %02x\n", cl->addr );
printk("DS1775 digital thermometer [@%02x]\n", cl->addr );
print_temp("Temp: ", temp );
print_temp(" Hyst: ", hyst_temp );
print_temp(" OS: ", os_temp );
printk("\n");
if( x.thermostat ) {
x.error |= 1;
goto out;
}
x.temp = temp;
x.thermostat = cl;
x.overheat_temp = os_temp;
x.overheat_hyst = hyst_temp;
cl->id = THERMOSTAT_CLIENT_ID;
strncpy( cl->name, "DS1775 thermostat", sizeof(cl->name) );
strlcpy( cl->name, "DS1775 thermostat", sizeof(cl->name) );
if( i2c_attach_client( cl ) )
goto out;
return 0;
if( !i2c_attach_client(cl) )
x.thermostat = cl;
out:
kfree( cl );
if( cl != x.thermostat )
kfree( cl );
return 0;
}
static int
do_detect( struct i2c_adapter *adapter, int addr, int kind )
do_probe( struct i2c_adapter *adapter, int addr, int kind )
{
struct i2c_client *cl;
if( strncmp(adapter->name, "uni-n", 5) )
return 0;
if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA
| I2C_FUNC_SMBUS_WRITE_BYTE) )
return 0;
if( !(cl=kmalloc( sizeof(struct i2c_client), GFP_KERNEL )) )
if( !(cl=kmalloc(sizeof(*cl), GFP_KERNEL)) )
return -ENOMEM;
memset( cl, 0, sizeof(struct i2c_client) );
......@@ -349,108 +443,94 @@ do_detect( struct i2c_adapter *adapter, int addr, int kind )
cl->flags = 0;
if( addr < 0x48 )
return detect_fan( cl );
return detect_thermostat( cl );
return attach_fan( cl );
return attach_thermostat( cl );
}
/************************************************************************/
/* initialization / cleanup */
/************************************************************************/
static int
therm_of_probe( struct of_device *dev, const struct of_match *match )
{
return i2c_add_driver( &g4fan_driver );
}
#define PRINT_REG( r ) printk("reg %02x = %02x\n", r, read_reg(x.fan, r, 1) )
static int
therm_of_remove( struct of_device *dev )
{
return i2c_del_driver( &g4fan_driver );
}
static struct of_match therm_of_match[] = {{
.name = "fan",
.type = OF_ANY_MATCH,
.compatible = "adm1030"
}, {}
};
static struct of_platform_driver therm_of_driver = {
.name = "temperature",
.match_table = therm_of_match,
.probe = therm_of_probe,
.remove = therm_of_remove,
};
struct apple_thermal_info {
u8 id; /* implementation ID */
u8 fan_count; /* number of fans */
u8 thermostat_count; /* number of thermostats */
u8 unused;
};
static int __init
g4fan_init( void )
{
struct apple_thermal_info *info;
struct device_node *np;
int ret, val;
np = of_find_node_by_name(NULL, "power-mgt");
if (np == NULL)
init_MUTEX( &x.lock );
if( !(np=of_find_node_by_name(NULL, "power-mgt")) )
return -ENODEV;
info = (struct apple_thermal_info*)get_property(np, "thermal-info", NULL);
of_node_put(np);
if (info == NULL)
return -ENODEV;
/* check for G4 "Windtunnel" SMP */
if( machine_is_compatible("PowerMac3,6") ) {
if( info->id != 3 ) {
printk(KERN_ERR "g4fan: design id %d unknown\n", info->id);
return -ENODEV;
}
} else {
printk(KERN_ERR "g4fan: unsupported machine type\n");
return -ENODEV;
}
if( (ret=i2c_add_driver(&g4fan_driver)) )
return ret;
if( !x.thermostat || !x.fan ) {
i2c_del_driver(&g4fan_driver );
if( !info || !machine_is_compatible("PowerMac3,6") )
return -ENODEV;
}
/* save registers (if we unload the module) */
x.r0 = read_reg( x.fan, 0x00, 1 );
x.r1 = read_reg( x.fan, 0x01, 1 );
x.r20 = read_reg( x.fan, 0x20, 1 );
x.r23 = read_reg( x.fan, 0x23, 1 );
x.r25 = read_reg( x.fan, 0x25, 1 );
/* improve measurement resolution (convergence time 1.5s) */
if( (val=read_reg( x.thermostat, 1, 1 )) >= 0 ) {
val |= 0x60;
if( write_reg( x.thermostat, 1, val, 1 ) )
printk("Failed writing config register\n");
if( info->id != 3 ) {
printk(KERN_ERR "therm_windtunnel: unsupported thermal design %d\n", info->id );
return -ENODEV;
}
/* disable interrupts and TAC input */
write_reg( x.fan, 0x01, 0x01, 1 );
/* enable filter */
write_reg( x.fan, 0x23, 0x91, 1 );
/* remote temp. controls fan */
write_reg( x.fan, 0x00, 0x95, 1 );
/* The thermostat (which besides measureing temperature controls
* has a THERM output which puts the fan on 100%) is usually
* set to kick in at 80 C (chip default). We reduce this a bit
* to be on the safe side (OSX doesn't)...
*/
if( x.overheat_temp == (80 << 8) ) {
x.overheat_temp = 65 << 8;
x.overheat_hyst = 60 << 8;
write_reg( x.thermostat, 2, x.overheat_hyst, 2 );
write_reg( x.thermostat, 3, x.overheat_temp, 2 );
if( !(np=of_find_node_by_name(NULL, "fan")) )
return -ENODEV;
x.of_dev = of_platform_device_create( np, "temperature" );
of_node_put( np );
print_temp("Reducing overheating limit to ", x.overheat_temp );
print_temp(" (Hyst: ", x.overheat_hyst );
printk(")\n");
if( !x.of_dev ) {
printk(KERN_ERR "Can't register fan controller!\n");
return -ENODEV;
}
/* set an initial fan setting */
x.upind = x.downind = 1;
tune_fan( fan_up_table[x.upind].fan_setting );
INIT_WORK(&poll_work, poll_temp, NULL);
init_timer( &x.timer );
x.timer.expires = jiffies + 8*HZ;
x.timer.function = schedule_poll;
add_timer( &x.timer );
of_register_driver( &therm_of_driver );
return 0;
}
static void __exit
g4fan_exit( void )
{
del_timer( &x.timer );
of_unregister_driver( &therm_of_driver );
write_reg( x.fan, 0x01, x.r1, 1 );
write_reg( x.fan, 0x20, x.r20, 1 );
write_reg( x.fan, 0x23, x.r23, 1 );
write_reg( x.fan, 0x25, x.r25, 1 );
write_reg( x.fan, 0x00, x.r0, 1 );
i2c_del_driver( &g4fan_driver );
if( x.of_dev )
of_device_unregister( x.of_dev );
}
module_init(g4fan_init);
module_exit(g4fan_exit);
MODULE_AUTHOR("Samuel Rydh <samuel@ibrium.se>");
MODULE_DESCRIPTION("Apple G4 (windtunnel) fan controller");
MODULE_LICENSE("GPL");
......@@ -1280,12 +1280,17 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return r;
}
#if 0
/* broken because some code assumes that multiple calls
to pci_alloc_consistent return data in the same 4GB segment.
This cannot work on machines with enough memory. */
if (!pci_set_consistent_dma_mask(pdev, mask))
dprintk((KERN_INFO MYNAM
": Using 64 bit consistent mask\n"));
else
dprintk((KERN_INFO MYNAM
": Not using 64 bit consistent mask\n"));
#endif
ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
if (ioc == NULL) {
......
......@@ -1256,7 +1256,6 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
SRpnt->sr_request->rq_disk = NULL; /* "sg" _disowns_ request blk */
srp->my_cmdp = NULL;
srp->done = 1;
SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
sdp->disk->disk_name, srp->header.pack_id, (int) SRpnt->sr_result));
......@@ -1312,8 +1311,9 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
}
if (sfp && srp) {
/* Now wake up any sg_read() that is waiting for this packet. */
wake_up_interruptible(&sfp->read_wait);
kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN);
srp->done = 1;
wake_up_interruptible(&sfp->read_wait);
}
}
......
......@@ -17,7 +17,7 @@
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
static char *verstr = "20040226";
static char *verstr = "20040318";
#include <linux/module.h>
......@@ -4193,20 +4193,25 @@ CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
static void do_create_class_files(Scsi_Tape *STp, int dev_num, int mode)
{
int rew, error;
int i, rew, error;
char name[10];
struct class_device *st_class_member;
if (!st_sysfs_class)
return;
for (rew=0; rew < 2; rew++) {
/* Make sure that the minor numbers corresponding to the four
first modes always get the same names */
i = mode << (4 - ST_NBR_MODE_BITS);
snprintf(name, 10, "%s%s%s", rew ? "n" : "",
STp->disk->disk_name, st_formats[i]);
st_class_member =
class_simple_device_add(st_sysfs_class,
MKDEV(SCSI_TAPE_MAJOR,
TAPE_MINOR(dev_num, mode, rew)),
&STp->device->sdev_gendev, "%s",
STp->modes[mode].cdevs[rew]->kobj.name);
if (!st_class_member) {
&STp->device->sdev_gendev, "%s", name);
if (IS_ERR(st_class_member)) {
printk(KERN_WARNING "st%d: class_simple_device_add failed\n",
dev_num);
goto out;
......
......@@ -550,7 +550,7 @@ static int do_open(struct block_device *bdev, struct file *file)
{
struct module *owner = NULL;
struct gendisk *disk;
int ret = -ENXIO;
int ret = -ENODEV;
int part;
file->f_mapping = bdev->bd_inode->i_mapping;
......@@ -563,6 +563,7 @@ static int do_open(struct block_device *bdev, struct file *file)
}
owner = disk->fops->owner;
ret = -ENXIO;
down(&bdev->bd_sem);
if (!bdev->bd_openers) {
bdev->bd_disk = disk;
......
......@@ -1004,7 +1004,8 @@ int do_sysctl_strategy (ctl_table *table,
* zero, proceed with automatic r/w */
if (table->data && table->maxlen) {
if (oldval && oldlenp) {
get_user(len, oldlenp);
if (get_user(len, oldlenp))
return -EFAULT;
if (len) {
if (len > table->maxlen)
len = table->maxlen;
......@@ -1303,7 +1304,7 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
len = 0;
p = buffer;
while (len < *lenp) {
if(get_user(c, p++))
if (get_user(c, p++))
return -EFAULT;
if (c == 0 || c == '\n')
break;
......@@ -1470,7 +1471,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
p = (char *) buffer;
while (left) {
char c;
if(get_user(c, p++))
if (get_user(c, p++))
return -EFAULT;
if (!isspace(c))
break;
......@@ -1705,7 +1706,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
p = (char *) buffer;
while (left) {
char c;
if(get_user(c, p++))
if (get_user(c, p++))
return -EFAULT;
if (!isspace(c))
break;
......@@ -1930,7 +1931,7 @@ int sysctl_string(ctl_table *table, int __user *name, int nlen,
return -ENOTDIR;
if (oldval && oldlenp) {
if(get_user(len, oldlenp))
if (get_user(len, oldlenp))
return -EFAULT;
if (len) {
l = strlen(table->data);
......@@ -1987,7 +1988,8 @@ int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
for (i = 0; i < length; i++) {
int value;
get_user(value, vec + i);
if (get_user(value, vec + i))
return -EFAULT;
if (min && value < min[i])
return -EINVAL;
if (max && value > max[i])
......
......@@ -685,8 +685,10 @@ DEBG("<stor");
}
STATIC int inflate_fixed(void)
/*
* We use `noinline' here to prevent gcc-3.5 from using too much stack space
*/
STATIC int noinline inflate_fixed(void)
/* decompress an inflated type 1 (fixed Huffman codes) block. We should
either replace this with a custom decoder, or at least precompute the
Huffman tables. */
......@@ -739,8 +741,10 @@ DEBG("<fix");
}
STATIC int inflate_dynamic(void)
/*
* We use `noinline' here to prevent gcc-3.5 from using too much stack space
*/
STATIC int noinline inflate_dynamic(void)
/* decompress an inflated type 2 (dynamic Huffman codes) block. */
{
int i; /* temporary variables */
......
......@@ -237,7 +237,7 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot)
len = PAGE_ALIGN(len);
end = start + len;
if (end < start)
return -EINVAL;
return -ENOMEM;
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
return -EINVAL;
if (end == start)
......
......@@ -576,7 +576,7 @@ static void __slab_error(const char *function, kmem_cache_t *cachep, char *msg)
* Add the CPU number into the expiry time to minimize the possibility of the
* CPUs getting into lockstep and contending for the global cache chain lock.
*/
static void __init start_cpu_timer(int cpu)
static void __devinit start_cpu_timer(int cpu)
{
struct timer_list *rt = &per_cpu(reap_timers, cpu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment