| 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, &reg[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, &reg[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

Reply via email to