[parisc-linux-cvs] simplified and speed-up the LED code

Helge Deller deller@gmx.de
Wed, 4 Jun 2003 02:48:02 +0200


--Boundary-00=_CHU3+c0VMZDZH8j
Content-Type: text/plain;
  charset="iso-8859-15"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Mittwoch, 4. Juni 2003 02:45, Helge Deller wrote:
> CVSROOT:	/var/cvs
> Module name:	linux-2.5
> Changes by:	deller	03/06/03 18:45:51
>
> Modified files:
> 	drivers/parisc : led.c
>
> Log message:
> simplified and speed-up the LED code


--Boundary-00=_CHU3+c0VMZDZH8j
Content-Type: text/plain;
  charset="iso-8859-15";
  name="diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="diff"

Index: led.c
===================================================================
RCS file: /var/cvs/linux-2.5/drivers/parisc/led.c,v
retrieving revision 1.9
diff -u -p -r1.9 led.c
--- led.c	2 Jun 2003 22:05:35 -0000	1.9
+++ led.c	4 Jun 2003 00:43:39 -0000
@@ -22,10 +22,11 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
-#include <linux/bitops.h>
 #include <linux/version.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/reboot.h>
@@ -59,10 +60,6 @@ static char lcd_text[32];
 #endif
 
 
-#define CALC_ADD(val, comp, add) \
- (val<=(comp/8) ? add/16 : val<=(comp/4) ? add/8 : val<=(comp/2) ? add/4 : add)
-
-
 struct lcd_block {
 	unsigned char command;	/* stores the command byte      */
 	unsigned char on;	/* value for turning LED on     */
@@ -341,77 +338,81 @@ static void led_LCD_driver(unsigned char
 
 /*
    ** 
-   ** led_get_net_stats()
+   ** led_get_net_activity()
    ** 
-   ** calculate the TX- & RX-troughput on the network interfaces in
-   ** the system for usage in the LED code
-   **
+   ** calculate if there was TX- or RX-troughput on the network interfaces
    ** (analog to dev_get_info() from net/core/dev.c)
    **   
  */
-static unsigned long led_net_rx_counter, led_net_tx_counter;
-
-static void led_get_net_stats(int addvalue)
+static __inline__ int led_get_net_activity(void)
 { 
-#ifdef CONFIG_NET
+#ifndef CONFIG_NET
+	return 0;
+#else
 	static unsigned long rx_total_last, tx_total_last;
 	unsigned long rx_total, tx_total;
 	struct net_device *dev;
-	struct net_device_stats *stats;
+	int retval;
 
 	rx_total = tx_total = 0;
 	
-	/* we are running as a tasklet, so locking dev_base 
+	/* we are running as tasklet, so locking dev_base 
 	 * for reading should be OK */
 	read_lock(&dev_base_lock);
-	for (dev = dev_base; dev != NULL; dev = dev->next) {
-	    if (dev->get_stats) { 
-	        stats = dev->get_stats(dev);
-		rx_total += stats->rx_packets;
-		tx_total += stats->tx_packets;
-	    }
+	for (dev = dev_base; dev; dev = dev->next) {
+	    struct net_device_stats *stats;
+	    struct in_device *in_dev = __in_dev_get(dev);
+	    if (!in_dev || !in_dev->ifa_list)
+		continue;
+	    if (LOOPBACK(in_dev->ifa_list->ifa_local))
+		continue;
+	    if (!dev->get_stats) 
+		continue;
+	    stats = dev->get_stats(dev);
+	    rx_total += stats->rx_packets;
+	    tx_total += stats->tx_packets;
 	}
 	read_unlock(&dev_base_lock);
 
-	rx_total -= rx_total_last;
-	tx_total -= tx_total_last;
-	
-	if (rx_total)
-	    led_net_rx_counter += CALC_ADD(rx_total, tx_total, addvalue);
+	retval = 0;
 
-	if (tx_total)
-	    led_net_tx_counter += CALC_ADD(tx_total, rx_total, addvalue);
-        
-	rx_total_last += rx_total;
-        tx_total_last += tx_total;
+	if (rx_total != rx_total_last) {
+		rx_total_last = rx_total;
+		retval |= LED_LAN_RCV;
+	}
+
+	if (tx_total != tx_total_last) {
+		tx_total_last = tx_total;
+		retval |= LED_LAN_TX;
+	}
+
+	return retval;
 #endif
 }
 
 
 /*
    ** 
-   ** led_get_diskio_stats()
+   ** led_get_diskio_activity()
    ** 
    ** calculate if there was disk-io in the system
    **   
  */
-static int led_get_diskio_stats(void)
+static __inline__ int led_get_diskio_activity(void)
 {	
-	unsigned int total;
-
-	struct page_state pgstat;
 	static unsigned long last_pgpgin, last_pgpgout;
+	struct page_state pgstat;
+	int changed;
 	
 	get_full_page_state(&pgstat); /* get no of sectors in & out */
 
 	/* Just use a very simple calculation here. Do not care about overflow,
 	   since we only want to know if there was activity or not. */
-	#define  DIFF_AND_SAVE(new,saved) (new-saved);  saved = new;
-	total  = DIFF_AND_SAVE(pgstat.pgpgin,  last_pgpgin);
-	total += DIFF_AND_SAVE(pgstat.pgpgout, last_pgpgout);
-        #undef   DIFF_AND_SAVE
+	changed = (pgstat.pgpgin != last_pgpgin) || (pgstat.pgpgout != last_pgpgout);
+	last_pgpgin  = pgstat.pgpgin;
+	last_pgpgout = pgstat.pgpgout;
 	
-	return total;
+	return (changed ? LED_DISK_IO : 0);
 }
 
 
@@ -427,16 +428,23 @@ static int led_get_diskio_stats(void)
     - optimizations
  */
 
-static unsigned char currentleds;	/* stores current value of the LEDs */
-
 #define HEARTBEAT_LEN (HZ*6/100)
 #define HEARTBEAT_2ND_RANGE_START (HZ*22/100)
 #define HEARTBEAT_2ND_RANGE_END   (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN)
 
+#if HZ==100
+ #define NORMALIZED_COUNT(count) (count)
+#else
+ #warning "Untested situation HZ != 100 !!"
+ #define NORMALIZED_COUNT(count) (count/(HZ/100))
+#endif
+
 static void led_tasklet_func(unsigned long unused)
 {
-	static unsigned int count, count_HZ;
 	static unsigned char lastleds;
+	unsigned char currentleds; /* stores current value of the LEDs */
+	static unsigned long count; /* static incremented value, not wrapped */
+	static unsigned long count_HZ; /* counter in range 0..HZ */
 
 	/* exit if not initialized */
 	if (!led_func_ptr)
@@ -447,6 +455,8 @@ static void led_tasklet_func(unsigned lo
 	if (++count_HZ == HZ)
 	    count_HZ = 0;
 
+	currentleds = lastleds;
+
 	if (led_heartbeat)
 	{
 		/* flash heartbeat-LED like a real heart (2 x short then a long delay) */
@@ -457,42 +467,25 @@ static void led_tasklet_func(unsigned lo
 		    currentleds &= ~LED_HEARTBEAT;
 	}
 
-	/* gather network and diskio statistics and flash LEDs respectively */
-
-	if (led_lanrxtx)
+	/* look for network activity and flash LEDs respectively */
+	if (led_lanrxtx && ((NORMALIZED_COUNT(count)+(8/2)) & 7) == 0)
 	{
-		if ((count & 31) == 0)
-			led_get_net_stats(30);
-
-		if (led_net_rx_counter) {
-			led_net_rx_counter--;
-			currentleds |= LED_LAN_RCV;
-		}
-		else    
-			currentleds &= ~LED_LAN_RCV;
-
-		if (led_net_tx_counter) {
-			led_net_tx_counter--;
-			currentleds |= LED_LAN_TX;
-		}
-		else    
-			currentleds &= ~LED_LAN_TX;
+		currentleds &= ~(LED_LAN_RCV | LED_LAN_TX);
+		currentleds |= led_get_net_activity();
 	}
 
-	if (led_diskio)
+	/* avoid to calculate diskio-stats at same irq  as netio-stats */
+	if (led_diskio && (NORMALIZED_COUNT(count) & 7) == 0)
 	{
-		static int last_diskio_found;
-
-		/* avoid to calculate diskio-stats at same irq as netio-stats ! */
-		if ((count & 7) == 7) 
-			last_diskio_found = led_get_diskio_stats();
-
-		if (last_diskio_found)
-			currentleds |= LED_DISK_IO;
-		else    
-			currentleds &= ~LED_DISK_IO;
+		currentleds &= ~LED_DISK_IO;
+		currentleds |= led_get_diskio_activity();
 	}
 
+	/* blink all LEDs twice a second if we got an Oops (HPMC) */
+	if (oops_in_progress) {
+		currentleds = (count_HZ<=(HZ/2)) ? 0 : 0xff;
+	}
+	
 	/* update the LCD/LEDs */
 	if (currentleds != lastleds) {
 	    led_func_ptr(currentleds);

--Boundary-00=_CHU3+c0VMZDZH8j--