| From: D. Hugh Redelmeier <[EMAIL PROTECTED]>
| Here are the top consumers of stack space in
| ivtv-0.3.2e/driver/cx25840-driver.c after my changes, but not Davids.
| I don't know the call graph, so I don't know if these need to be added
| together.
|
| 2632 setting_sequencer
| 1576 cx25840_detect_client
| 1384 cx25840_command
| 456 set_default_values
I've hacked on setting_sequencer and have reduced its requirement
significantly. Unfortunately, I don't have a way of testing my
changes. Could someone else try? On a 4KSTACKS system?
Here is what I did:
- I added "static" to as many externals as I could. This is good
hygiene, but has no important effect.
- I tidied up the CX25840__MAGIC_START mechanism in cx25840-registers.h
In the process, I got rid of the unexplained 0xAA, 0x55, 0xBB, 0x44
literals in cx25840-driver.c
- I changed the debugging output of register setting to limit lines to
16 registers per line. This is the important change: it reduced
the stack requirement of setting_sequencer from 2632 bytes to 872.
- I put spaces between the characters of =& and of =*. These
sequences used to have different meanings and should be avoided.
- renamed each local variable "l" to "w". The reason is that many
terminals make it hard to distinguish "l" from "1". "l" stood
for "length"; "w" stands for "width".
The stack space required by setting_sequencer could easily be reduced
by another 300+ bytes by converting "dirty" to a bit array. I thought
that it would be better to test this code first.
Any volunteers?
The starting point for these diffs is ivtv-0.3.2e plus the patches to
cx25840-driver.c that I sent to the list yesterday. See
<http://sourceforge.net/mailarchive/message.php?msg_id=10952646>
Or see the 18th message in:
<http://www.gossamer-threads.com/lists/ivtv/devel/17857>
===================================================================
RCS file: RCS/cx25840-driver.c,v
retrieving revision 1.2
diff -u -r1.2 cx25840-driver.c
--- cx25840-driver.c 2005/02/24 18:38:47 1.2
+++ cx25840-driver.c 2005/02/24 21:58:41
@@ -113,7 +113,7 @@
static int cx25840_input_layout[] = {-1,-1,-1,-1,-1,-1,-1};
-int pvr_150_input_layout[] = {CX25840_SVIDEO,
+static int pvr_150_input_layout[] = {CX25840_SVIDEO,
CX25840_SVIDEO,
CX25840_COMPOSITE,
CX25840_COMPOSITE,
@@ -122,7 +122,7 @@
CX25840_TUNER,
-1};
-int pvr_500_input_layout[] = {CX25840_SVIDEO,
+static int pvr_500_input_layout[] = {CX25840_SVIDEO,
CX25840_SVIDEO,
CX25840_COMPOSITE,
CX25840_COMPOSITE,
@@ -131,7 +131,7 @@
CX25840_TUNER,
CX25840_TUNER};
-int pg_600_input_layout[] = {CX25840_SVIDEO,
+static int pg_600_input_layout[] = {CX25840_SVIDEO,
CX25840_TUNER,
CX25840_COMPOSITE,
CX25840_FM,
@@ -139,7 +139,7 @@
-1,-1};
/* ----------------------------------------------------------------------- */
-void cx25840_analyze(int ptr, __u8 byte) {
+static void cx25840_analyze(int ptr, __u8 byte) {
int i;
__u8 covered=0;
for(i=0; i<number_of_settings; i++) {
@@ -218,7 +218,7 @@
#define I_cx25840 0x44
#define wm8775 0x1b
-void set_default_values(struct i2c_client *client) {
+static void set_default_values(struct i2c_client *client) {
struct cx25840_state *state=i2c_get_clientdata(client);
int i;
int ret;
@@ -259,73 +259,91 @@
memset (dirt, 0, sizeof(dirt));
do {
__u16 setting;
- if (ptr[0]!=0xAA||ptr[1]!=0x55) break; ptr+=2;
+ if (ptr[0]!=CX25840__MAGIC_START1 || ptr[1]!=CX25840__MAGIC_START2) break;
ptr+=2;
setting=CX25840_SEQUENCE_GET_SETTING(ptr);
if (setting==special_WI2C_setting) {
u8 len=ptr[2];
// This is ugly but effective for development.....
u16 saddr=client->addr;
u16 naddr=ptr[3];
- const u8 *i2c_data =&ptr[4];
+ const u8 *i2c_data = &ptr[4];
int ret;
ptr+=2+2+len;
- if (ptr[0]!=0xBB||ptr[1]!=0x44) break; ptr+=2;
+ if (ptr[0]!=CX25840__MAGIC_END1 || ptr[1]!=CX25840__MAGIC_END2) break;
ptr+=2;
client->addr=naddr;
ret=i2c_master_send(client, i2c_data, len);
client->addr=saddr;
if(ret!=len) { ERR("I2C sequence write failed, length %d, ret %d", len,
ret); }
} else if (setting==special_delay_setting) {
- int utime=*ptr;
+ int utime = *ptr;
ptr++;
- if (ptr[0]!=0xBB||ptr[1]!=0x44) break; ptr+=2;
+ if (ptr[0]!=CX25840__MAGIC_END1 || ptr[1]!=CX25840__MAGIC_END2) break;
ptr+=2;
DEBUG(3, "Delay: '%d'uS",utime);
udelay(utime);
} else if (setting==special_execute_setting) {
int i;
ptr+=2;
- if (ptr[0]!=0xBB||ptr[1]!=0x44) break; ptr+=2;
+ if (ptr[0]!=CX25840__MAGIC_END1 || ptr[1]!=CX25840__MAGIC_END2) break;
ptr+=2;
DEBUG(2, "Executing settings.");
for(i=0;i<number_of_registers;i++)
if (dirt[i]) {
int ret;
- int l=0;
- while
((i+l)<number_of_registers&&dirt[i+l]&&(CX25840_REGISTER_ADDRESS(i)+l==CX25840_REGISTER_ADDRESS(i+l)))
l++;
+ int w=0;
+ while
((i+w)<number_of_registers&&dirt[i+w]&&(CX25840_REGISTER_ADDRESS(i)+w==CX25840_REGISTER_ADDRESS(i+w)))
w++;
reg[i-1]=CX25840_REGISTER_ADDRESS(i)&0xff;
reg[i-2]=(CX25840_REGISTER_ADDRESS(i)>>8)&0xff;
- ret=i2c_master_send(client, ®[i-2], l+2);
- if(ret!=(l+2)) { ERR("I2C sequence write failed, length %d, ret %d",
l+2, ret); fail++; }
- {
- char buff[number_of_registers*5+1];
- char *p=buff;
- int ii;
- for(ii=i-2;ii<i+l;ii++) p+=sprintf(p,"0x%02x,",reg[ii]);
- for(ii=i;ii<i+l;ii++) state->reg_cache[ii]=reg[ii];
- DEBUG(3, "Sending to 0x%04x len %d %s",
CX25840_REGISTER_ADDRESS(i), l+2, buff);
- i+=l-1;
- }
+ ret=i2c_master_send(client, ®[i-2], w+2);
+ if(ret!=(w+2)) { ERR("I2C sequence write failed, length %d, ret %d",
w+2, ret); fail++; }
+ if (debug >= 3) {
+ int ii = i - 2;
+ int iw = w + 2;
+ int first = 1;
+
+ while (iw != 0) {
+# define REGS_PER_LINE 16
+ char buff[REGS_PER_LINE * 3 + 1];
+ char *p = buff;
+
+ while (iw != 0 && p < &buff[sizeof(buff) - 1]) {
+ p += sprintf(p, " %02x", reg[ii++]);
+ iw--;
+ }
+ if (first)
+ DEBUG(3, "Sending to 0x%04x len %d %s",
+ CX25840_REGISTER_ADDRESS(i), w + 2, buff);
+ else
+ DEBUG(3, "\t%s", buff);
+ first = 0;
+# undef REGS_PER_LINE
+ }
+ }
+
+ for (; w > 0; i++, w--)
+ state->reg_cache[i] = reg[i];
+ i--; /* will be incremented by the enclosing for */
}
memset (dirt, 0, sizeof(dirt));
} else if (setting==special_tag_setting) {
const char *tag=CX25840_SEQUENCE_GET_TAG(ptr);
ptr+=CX25840_SEQUENCE_GET_TAG_LENGTH(ptr);
- if (ptr[0]!=0xBB||ptr[1]!=0x44) break; ptr+=2;
+ if (ptr[0]!=CX25840__MAGIC_END1 || ptr[1]!=CX25840__MAGIC_END2) break;
ptr+=2;
DEBUG(1, "Sequence tag: '%s'",tag);
} else if (setting==special_end_setting) {
ptr+=2;
- if (ptr[0]!=0xBB||ptr[1]!=0x44) break; ptr+=2;
- DEBUG(2, "Succesfully handled sequence of %d settings.", cnt);
+ if (ptr[0]!=CX25840__MAGIC_END1 || ptr[1]!=CX25840__MAGIC_END2) break;
ptr+=2;
+ DEBUG(2, "Successfully handled sequence of %d settings.", cnt);
return;
} else {
__u32 value=CX25840_SEQUENCE_GET_VALUE(ptr);
__u32 debvalue=value;
int i=CX25840_SETTING_REGISTER_INDEX(setting);
int s=CX25840_SETTING_START_BIT(setting);
- int l=CX25840_SETTING_BIT_LENGTH(setting);
+ int w=CX25840_SETTING_BIT_LENGTH(setting);
int modified=0;
ptr+=CX25840_SEQUENCE_GET_LENGTH(ptr);
- if (ptr[0]!=0xBB||ptr[1]!=0x44) break; ptr+=2;
- while(l>0) {
+ if (ptr[0]!=CX25840__MAGIC_END1 || ptr[1]!=CX25840__MAGIC_END2) break;
ptr+=2;
+ while(w>0) {
__u8 old;
- __u8 mask=(0xff>>(8-(l>8?8:l)))<<s;
+ __u8 mask = ~(~0U << w) << s;
if (!dirt[i]) {
dirt[i]=1;
reg[i]=state->reg_cache[i];
@@ -333,7 +351,7 @@
old=reg[i];
reg[i]=(reg[i]&~mask)|(mask&(value<<s));
modified=modified||(old!=reg[i]);
- l-=8-s;
+ w-=8-s;
value>>=(8-s);
s=0;
i++;
@@ -347,11 +365,11 @@
IE("Offtrack in setting sequence after %d settings 0x%02x%02x", cnt, ptr[0],
ptr[1]);
}
-__u32 read_setting(struct i2c_client *client, __u16 setting) {
+static __u32 read_setting(struct i2c_client *client, __u16 setting) {
struct cx25840_state *state=i2c_get_clientdata(client);
int i;
int s;
- int l;
+ int w;
int rl;
__u32 value;
int ret;
@@ -360,16 +378,16 @@
}
i=CX25840_SETTING_REGISTER_INDEX(setting);
s=CX25840_SETTING_START_BIT(setting);
- l=CX25840_SETTING_BIT_LENGTH(setting);
- rl=(s+l+7)/8;
+ w=CX25840_SETTING_BIT_LENGTH(setting);
+ rl=(s+w+7)/8;
if (CX25840_SETTING_TYPE(setting)!=RW) {
char buff[2]; buff[0]=CX25840_REGISTER_ADDRESS(i)>>8;
buff[1]=CX25840_REGISTER_ADDRESS(i)&0xff;
ret=i2c_master_send(client, buff, 2);
if(ret!=2) {
- ERR("I2C write failed, length %d, ret %d", l+2, ret);
+ ERR("I2C write failed, length %d, ret %d", w+2, ret);
} else {
ret=i2c_master_recv(client, &state->reg_cache[i], rl);
- if(ret!=rl) { ERR("I2C sequence recv failed, length %d, ret %d", l+2,
ret); }
+ if(ret!=rl) { ERR("I2C sequence recv failed, length %d, ret %d", w+2,
ret); }
}
}
value=state->reg_cache[i]>>s;
@@ -378,14 +396,14 @@
if(rl==0) break;
value|=(state->reg_cache[i]<<-s);
} while (1);
- return value&(0xffffffff>>(32-l));
+ return value&(0xffffffff>>(32-w));
}
static void do_cx25840_dump(struct i2c_client *client) {
int addr;
u8 cmd[2], byte;
char buff[5*256+10], *sptr=0, *lptr=0;
- int l=0;
+ int w=0;
addr=0;
DEBUG(3, "Dump of regs != 0x00");
@@ -395,18 +413,18 @@
i2c_master_send(client, cmd, 2);
i2c_master_recv(client, &byte, 1);
if (byte) {
- if (l==0) {
+ if (w==0) {
sptr=buff+sprintf(buff, "D(0x%04x, ", addr);
lptr=sptr; sptr+=5;
}
sptr+=sprintf(sptr, ",0x%02x", byte);
- l++;
+ w++;
}
addr++;
- if (l&&(!byte||!addr%16||addr==4*1024)) {
- sprintf(lptr, "%4d", l); lptr[4]=' ';
+ if (w&&(!byte||!addr%16||addr==4*1024)) {
+ sprintf(lptr, "%4d", w); lptr[4]=' ';
DEBUG(3, "%s);", buff);
- l=0;
+ w=0;
}
}
}
@@ -1410,7 +1428,7 @@
I2C_CLIENT_INSMOD;
static int cx25840_i2c_id = 0;
-struct i2c_driver i2c_driver_cx25840;
+static struct i2c_driver i2c_driver_cx25840;
static int cx25840_detect_client (struct i2c_adapter *adapter,
int address,
@@ -1506,7 +1524,7 @@
}
/* i2c implementation */
-struct i2c_driver i2c_driver_cx25840 = {
+static struct i2c_driver i2c_driver_cx25840 = {
.name = "cx25840",
.id = I2C_DRIVERID_CX25840,
===================================================================
RCS file: RCS/cx25840-registers.h,v
retrieving revision 1.1
diff -u -r1.1 cx25840-registers.h
--- cx25840-registers.h 2005/02/24 19:29:29 1.1
+++ cx25840-registers.h 2005/02/24 21:14:42
@@ -20,7 +20,7 @@
unsigned int value;
char *name;
} value_map;
-typedef struct {
+typedef const struct {
__u32 location; // bit0-8 reg 9-11 start 12-16 len 17-20 type
__u32 default_value;
char *name;
@@ -416,19 +416,24 @@
#define CX25840_SEQUENCE_GET_TAG(ptr) (ptr+2)
-#define CX25840__MAGIC_START 0xAA,0x55,
-#define CX25840__MAGIC_END ,0xBB,0x44
+#define CX25840__MAGIC_START1 0xAA
+#define CX25840__MAGIC_START2 0x55
+#define CX25840__MAGIC_START(sv6) CX25840__MAGIC_START1,
CX25840__MAGIC_START2, (sv6) & 0xFF, ((sv6)>>8) & 0xFF
-#define CX25840_TAG(args...) CX25840__MAGIC_START
(special_tag_setting&0xff), (special_tag_setting>>8) ,args, 0
CX25840__MAGIC_END
-#define WI2C(len,i2caddr,args...) CX25840__MAGIC_START
(special_WI2C_setting&0xff), (special_WI2C_setting>>8) ,len,i2caddr,args
CX25840__MAGIC_END
-#define CX25840_DELAY(utime) CX25840__MAGIC_START
(special_delay_setting&0xff), (special_delay_setting>>8) ,utime
CX25840__MAGIC_END
+#define CX25840__MAGIC_END1 0xBB
+#define CX25840__MAGIC_END2 0x44
+#define CX25840__MAGIC_END CX25840__MAGIC_END1,
CX25840__MAGIC_END2
+
+#define CX25840_TAG(args...)
CX25840__MAGIC_START(special_tag_setting) ,args, 0,
CX25840__MAGIC_END
+#define WI2C(len,i2caddr,args...)
CX25840__MAGIC_START(special_WI2C_setting) ,len,i2caddr,args,
CX25840__MAGIC_END
+#define CX25840_DELAY(utime)
CX25840__MAGIC_START(special_delay_setting) ,utime,
CX25840__MAGIC_END
#define CX25840_END
CX25840__SEQUENCE_6BIT(special_end_setting, 0)
#define CX25840_EXECUTE
CX25840__SEQUENCE_6BIT(special_execute_setting, 0)
-#define CX25840__SEQUENCE_6BIT(set, value) CX25840__MAGIC_START
(set&0xff), (set>>8)|(((value)<<2)&0xff) CX25840__MAGIC_END
-#define CX25840__SEQUENCE_14BIT(set, value) CX25840__MAGIC_START
(set&0xff), (set>>8)|(((value)<<2)&0xff),((value)>>6&0xff) CX25840__MAGIC_END
-#define CX25840__SEQUENCE_22BIT(set, value) CX25840__MAGIC_START
(set&0xff), (set>>8)|(((value)<<2)&0xff),((value)>>6&0xff),((value)>>14&0xff)
CX25840__MAGIC_END
-#define CX25840__SEQUENCE_30BIT(set, value) CX25840__MAGIC_START
(set&0xff),
(set>>8)|(((value)<<2)&0xff),((value)>>6&0xff),((value)>>14&0xff),((value)>>22&0xff)
CX25840__MAGIC_END
-#define CX25840__SEQUENCE_32BIT(set, value) CX25840__MAGIC_START
(set&0xff),
(set>>8)|(((value)<<2)&0xff),((value)>>6&0xff),((value)>>14&0xff),((value)>>22&0xff),((value)>>30&0xff)
CX25840__MAGIC_END
+#define CX25840__SEQUENCE_6BIT(set, value) CX25840__MAGIC_START((set) |
((value)<<10)), CX25840__MAGIC_END
+#define CX25840__SEQUENCE_14BIT(set, value) CX25840__MAGIC_START((set) |
((value)<<10)), (value)>>6&0xff, CX25840__MAGIC_END
+#define CX25840__SEQUENCE_22BIT(set, value) CX25840__MAGIC_START((set) |
((value)<<10)), (value)>>6&0xff, (value)>>14&0xff, CX25840__MAGIC_END
+#define CX25840__SEQUENCE_30BIT(set, value) CX25840__MAGIC_START((set) |
((value)<<10)), (value)>>6&0xff, (value)>>14&0xff, (value)>>22&0xff,
CX25840__MAGIC_END
+#define CX25840__SEQUENCE_32BIT(set, value) CX25840__MAGIC_START((set) |
((value)<<10)), (value)>>6&0xff, (value)>>14&0xff, (value)>>22&0xff,
(value)>>30&0xff, CX25840__MAGIC_END
#define CX25840_SET_SLEEP(value) CX25840__SEQUENCE_6BIT(SLEEP, value)
#define CX25840_SET_DIGITAL_PWR_DN(value)
CX25840__SEQUENCE_6BIT(DIGITAL_PWR_DN, value)
#define CX25840_SET_REF_CLK_SEL(value) CX25840__SEQUENCE_6BIT(REF_CLK_SEL,
value)
===================================================================
-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
ivtv-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ivtv-devel