Ticket #10731: backport_ag7240_switch_led_support.patch

File backport_ag7240_switch_led_support.patch, 23.8 KB (added by magyarsz, 4 years ago)
  • package/base-files/files/etc/init.d/led

    a b  
    2424 
    2525        [ -e /sys/class/leds/${sysfs}/brightness ] && { 
    2626                echo "setting up led ${name}" 
    27                 [ "$default" != nil ] && {  
    28                         [ $default -eq 1 ] &&  
    29                                 echo 1 >/sys/class/leds/${sysfs}/brightness  
     27                [ "$default" != nil ] && { 
     28                        [ $default -eq 1 ] && 
     29                                echo 1 >/sys/class/leds/${sysfs}/brightness 
    3030                        [ $default -eq 1 ] || 
    3131                                echo 0 >/sys/class/leds/${sysfs}/brightness 
    3232                } 
    3333                echo $trigger > /sys/class/leds/${sysfs}/trigger 
    34                 [ "$trigger" == "netdev" -a -n "$dev" ] && { 
    35                         echo $dev > /sys/class/leds/${sysfs}/device_name 
    36                         echo $mode > /sys/class/leds/${sysfs}/mode 
    37                 }  
    38                 [ "$trigger" == "timer" ] && { 
    39                         [ -n "$delayon" ] && echo $delayon > /sys/class/leds/${sysfs}/delay_on 
    40                         [ -n "$delayoff" ] && echo $delayoff > /sys/class/leds/${sysfs}/delay_off 
    41                 } 
     34                case "$trigger" in 
     35                "netdev") 
     36                        [ -n "$dev" ] && { 
     37                                echo $dev > /sys/class/leds/${sysfs}/device_name 
     38                                echo $mode > /sys/class/leds/${sysfs}/mode 
     39                        } 
     40                        ;; 
     41 
     42                "timer") 
     43                        [ -n "$delayon" ] && \ 
     44                                echo $delayon > /sys/class/leds/${sysfs}/delay_on 
     45                        [ -n "$delayoff" ] && \ 
     46                                echo $delayoff > /sys/class/leds/${sysfs}/delay_off 
     47                        ;; 
     48 
     49                switch[0-9]*) 
     50                        local port_mask 
     51 
     52                        config_get port_mask $1 port_mask 
     53                        [ -n "$port_mask" ] && \ 
     54                                echo $port_mask > /sys/class/leds/${sysfs}/port_mask 
     55                        ;; 
     56                esac 
    4257        } 
    4358} 
    4459 
  • package/base-files/Makefile

    a b  
    1010include $(INCLUDE_DIR)/kernel.mk 
    1111 
    1212PKG_NAME:=base-files 
    13 PKG_RELEASE:=43.32 
     13PKG_RELEASE:=43.33 
    1414 
    1515PKG_FILE_DEPENDS:=$(PLATFORM_DIR)/ $(GENERIC_PLATFORM_DIR)/base-files/ 
    1616PKG_BUILD_DEPENDS:=opkg/host 
  • target/linux/ar71xx/base-files/etc/uci-defaults/tl-wr741nd

    a b  
     1#!/bin/sh 
     2# 
     3# Copyright (C) 2010 OpenWrt.org 
     4# 
     5 
     6. /lib/ar71xx.sh 
     7 
     8board=$(ar71xx_board_name) 
     9 
     10tl_wr741nd_set_eth_leds() { 
     11        uci batch <<EOF 
     12set system.led_wan='led' 
     13set system.led_wan.name='WAN' 
     14set system.led_wan.sysfs='tl-wr741nd:green:wan' 
     15set system.led_wan.trigger='netdev' 
     16set system.led_wan.dev='eth1' 
     17set system.led_wan.mode='link tx rx' 
     18set system.led_lan1='led' 
     19set system.led_lan1.name='LAN1' 
     20set system.led_lan1.sysfs='tl-wr741nd:green:lan1' 
     21set system.led_lan1.trigger='switch0' 
     22set system.led_lan1.port_mask='0x02' 
     23set system.led_lan2='led' 
     24set system.led_lan2.name='LAN2' 
     25set system.led_lan2.sysfs='tl-wr741nd:green:lan2' 
     26set system.led_lan2.trigger='switch0' 
     27set system.led_lan2.port_mask='0x04' 
     28set system.led_lan3='led' 
     29set system.led_lan3.name='LAN3' 
     30set system.led_lan3.sysfs='tl-wr741nd:green:lan3' 
     31set system.led_lan3.trigger='switch0' 
     32set system.led_lan3.port_mask='0x08' 
     33set system.led_lan4='led' 
     34set system.led_lan4.name='LAN4' 
     35set system.led_lan4.sysfs='tl-wr741nd:green:lan4' 
     36set system.led_lan4.trigger='switch0' 
     37set system.led_lan4.port_mask='0x10' 
     38commit system 
     39EOF 
     40} 
     41 
     42if [ "${board}" == "tl-wr741nd" ]; then 
     43        tl_wr741nd_set_eth_leds 
     44fi 
  • target/linux/ar71xx/config-2.6.32

    a b  
    228228# CONFIG_SPI_SPIDEV is not set 
    229229# CONFIG_SPI_VSC7385 is not set 
    230230CONFIG_SWCONFIG=y 
     231CONFIG_SWCONFIG_LEDS=y 
    231232CONFIG_SYS_HAS_CPU_MIPS32_R1=y 
    232233CONFIG_SYS_HAS_CPU_MIPS32_R2=y 
    233234CONFIG_SYS_HAS_EARLY_PRINTK=y 
  • target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr741nd.c

    a b  
    2222 
    2323#define TL_WR741ND_GPIO_LED_QSS         0 
    2424#define TL_WR741ND_GPIO_LED_SYSTEM      1 
     25#define TL_WR741ND_GPIO_LED_LAN1        13 
     26#define TL_WR741ND_GPIO_LED_LAN2        14 
     27#define TL_WR741ND_GPIO_LED_LAN3        15 
     28#define TL_WR741ND_GPIO_LED_LAN4        16 
     29#define TL_WR741ND_GPIO_LED_WAN         17 
    2530 
    2631#define TL_WR741ND_GPIO_BTN_RESET       11 
    2732#define TL_WR741ND_GPIO_BTN_QSS         12 
     
    7277                .name           = "tl-wr741nd:green:qss", 
    7378                .gpio           = TL_WR741ND_GPIO_LED_QSS, 
    7479                .active_low     = 1, 
     80        }, { 
     81                .name           = "tl-wr741nd:green:lan1", 
     82                .gpio           = TL_WR741ND_GPIO_LED_LAN1, 
     83                .active_low     = 1, 
     84        }, { 
     85                .name           = "tl-wr741nd:green:lan2", 
     86                .gpio           = TL_WR741ND_GPIO_LED_LAN2, 
     87                .active_low     = 1, 
     88        }, { 
     89                .name           = "tl-wr741nd:green:lan3", 
     90                .gpio           = TL_WR741ND_GPIO_LED_LAN3, 
     91                .active_low     = 1, 
     92        }, { 
     93                .name           = "tl-wr741nd:green:lan4", 
     94                .gpio           = TL_WR741ND_GPIO_LED_LAN4, 
     95                .active_low     = 1, 
     96        }, { 
     97                .name           = "tl-wr741nd:green:wan", 
     98                .gpio           = TL_WR741ND_GPIO_LED_WAN, 
     99                .active_low     = 1, 
    75100        } 
    76101}; 
    77102 
     
    98123        u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); 
    99124        u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); 
    100125 
     126        ar71xx_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | 
     127                                     AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | 
     128                                     AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | 
     129                                     AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | 
     130                                     AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); 
     131 
    101132        ar71xx_add_device_m25p80(&tl_wr741nd_flash_data); 
    102133 
    103134        ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tl_wr741nd_leds_gpio), 
  • target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c

    a b  
    9696#define AR7240_REG_PORT_BASE(_port)     (0x100 + (_port) * 0x100) 
    9797 
    9898#define AR7240_REG_PORT_STATUS(_port)   (AR7240_REG_PORT_BASE((_port)) + 0x00) 
     99#define AR7240_PORT_STATUS_SPEED_S      0 
    99100#define AR7240_PORT_STATUS_SPEED_M      BITM(2) 
    100101#define AR7240_PORT_STATUS_SPEED_10     0 
    101102#define AR7240_PORT_STATUS_SPEED_100    1 
     
    199200 
    200201#define sw_to_ar7240(_dev) container_of(_dev, struct ar7240sw, swdev) 
    201202 
     203struct ar7240sw_port_stat { 
     204        unsigned long rx_broadcast; 
     205        unsigned long rx_pause; 
     206        unsigned long rx_multicast; 
     207        unsigned long rx_fcs_error; 
     208        unsigned long rx_align_error; 
     209        unsigned long rx_runt; 
     210        unsigned long rx_fragments; 
     211        unsigned long rx_64byte; 
     212        unsigned long rx_128byte; 
     213        unsigned long rx_256byte; 
     214        unsigned long rx_512byte; 
     215        unsigned long rx_1024byte; 
     216        unsigned long rx_1518byte; 
     217        unsigned long rx_maxbyte; 
     218        unsigned long rx_toolong; 
     219        unsigned long rx_good_byte; 
     220        unsigned long rx_bad_byte; 
     221        unsigned long rx_overflow; 
     222        unsigned long filtered; 
     223 
     224        unsigned long tx_broadcast; 
     225        unsigned long tx_pause; 
     226        unsigned long tx_multicast; 
     227        unsigned long tx_underrun; 
     228        unsigned long tx_64byte; 
     229        unsigned long tx_128byte; 
     230        unsigned long tx_256byte; 
     231        unsigned long tx_512byte; 
     232        unsigned long tx_1024byte; 
     233        unsigned long tx_1518byte; 
     234        unsigned long tx_maxbyte; 
     235        unsigned long tx_oversize; 
     236        unsigned long tx_byte; 
     237        unsigned long tx_collision; 
     238        unsigned long tx_abortcol; 
     239        unsigned long tx_multicol; 
     240        unsigned long tx_singlecol; 
     241        unsigned long tx_excdefer; 
     242        unsigned long tx_defer; 
     243        unsigned long tx_xlatecol; 
     244}; 
     245 
    202246struct ar7240sw { 
    203247        struct mii_bus  *mii_bus; 
    204248        struct switch_dev swdev; 
     
    207251        u8 vlan_table[AR7240_MAX_VLANS]; 
    208252        u8 vlan_tagged; 
    209253        u16 pvid[AR7240_NUM_PORTS]; 
     254        char buf[80]; 
     255 
     256        rwlock_t stats_lock; 
     257        struct ar7240sw_port_stat port_stats[AR7240_NUM_PORTS]; 
    210258}; 
    211259 
    212260struct ar7240sw_hw_stat { 
     
    400448static int ar7240sw_capture_stats(struct ar7240sw *as) 
    401449{ 
    402450        struct mii_bus *mii = as->mii_bus; 
     451        int port; 
    403452        int ret; 
    404453 
     454        write_lock(&as->stats_lock); 
     455 
    405456        /* Capture the hardware statistics for all ports */ 
    406457        ar7240sw_reg_write(mii, AR7240_REG_MIB_FUNCTION0, 
    407458                           (AR7240_MIB_FUNC_CAPTURE << AR7240_MIB_FUNC_S)); 
     
    409460        /* Wait for the capturing to complete. */ 
    410461        ret = ar7240sw_reg_wait(mii, AR7240_REG_MIB_FUNCTION0, 
    411462                                AR7240_MIB_BUSY, 0, 10); 
     463 
     464        if (ret) 
     465                goto unlock; 
     466 
     467        for (port = 0; port < AR7240_NUM_PORTS; port++) { 
     468                unsigned int base; 
     469                struct ar7240sw_port_stat *stats; 
     470 
     471                base = AR7240_REG_STATS_BASE(port); 
     472                stats = &as->port_stats[port]; 
     473 
     474#define READ_STAT(_r) ar7240sw_reg_read(mii, base + AR7240_STATS_ ## _r) 
     475 
     476                stats->rx_good_byte += READ_STAT(RXGOODBYTE); 
     477                stats->tx_byte += READ_STAT(TXBYTE); 
     478 
     479#undef READ_STAT 
     480        } 
     481 
     482        ret = 0; 
     483 
     484unlock: 
     485        write_unlock(&as->stats_lock); 
    412486        return ret; 
    413487} 
    414488 
     
    660734        return 0; 
    661735} 
    662736 
     737static const char * 
     738ar7240_speed_str(u32 status) 
     739{ 
     740        u32 speed; 
     741 
     742        speed = (status >> AR7240_PORT_STATUS_SPEED_S) & 
     743                                        AR7240_PORT_STATUS_SPEED_M; 
     744        switch (speed) { 
     745        case AR7240_PORT_STATUS_SPEED_10: 
     746                return "10baseT"; 
     747        case AR7240_PORT_STATUS_SPEED_100: 
     748                return "100baseT"; 
     749        case AR7240_PORT_STATUS_SPEED_1000: 
     750                return "1000baseT"; 
     751        } 
     752 
     753        return "unknown"; 
     754} 
     755 
     756static int 
     757ar7240_port_get_link(struct switch_dev *dev, const struct switch_attr *attr, 
     758                     struct switch_val *val) 
     759{ 
     760        struct ar7240sw *as = sw_to_ar7240(dev); 
     761        struct mii_bus *mii = as->mii_bus; 
     762        u32 len; 
     763        u32 status; 
     764        int port; 
     765 
     766        port = val->port_vlan; 
     767 
     768        memset(as->buf, '\0', sizeof(as->buf)); 
     769        status = ar7240sw_reg_read(mii, AR7240_REG_PORT_STATUS(port)); 
     770 
     771        if (status & AR7240_PORT_STATUS_LINK_UP) { 
     772                len = snprintf(as->buf, sizeof(as->buf), 
     773                                "port:%d link:up speed:%s %s-duplex %s%s%s", 
     774                                port, 
     775                                ar7240_speed_str(status), 
     776                                (status & AR7240_PORT_STATUS_DUPLEX) ? 
     777                                        "full" : "half", 
     778                                (status & AR7240_PORT_STATUS_TXFLOW) ? 
     779                                        "txflow ": "", 
     780                                (status & AR7240_PORT_STATUS_RXFLOW) ? 
     781                                        "rxflow " : "", 
     782                                (status & AR7240_PORT_STATUS_LINK_AUTO) ? 
     783                                        "auto ": ""); 
     784        } else { 
     785                len = snprintf(as->buf, sizeof(as->buf), 
     786                               "port:%d link:down", port); 
     787        } 
     788 
     789        val->value.s = as->buf; 
     790        val->len = len; 
     791 
     792        return 0; 
     793} 
    663794 
    664795static void 
    665796ar7240_vtu_op(struct ar7240sw *as, u32 op, u32 val) 
     
    736867        return 0; 
    737868} 
    738869 
     870static int 
     871ar7240_get_port_link(struct switch_dev *dev, int port, 
     872                     struct switch_port_link *link) 
     873{ 
     874        struct ar7240sw *as = sw_to_ar7240(dev); 
     875        struct mii_bus *mii = as->mii_bus; 
     876        u32 status; 
     877 
     878        if (port > AR7240_NUM_PORTS) 
     879                return -EINVAL; 
     880 
     881        status = ar7240sw_reg_read(mii, AR7240_REG_PORT_STATUS(port)); 
     882 
     883        link->link = !!(status & AR7240_PORT_STATUS_LINK_UP); 
     884        link->aneg = !!(status & AR7240_PORT_STATUS_LINK_AUTO); 
     885        link->duplex = !!(status & AR7240_PORT_STATUS_DUPLEX); 
     886        link->tx_flow = !!(status & AR7240_PORT_STATUS_TXFLOW); 
     887        link->rx_flow = !!(status & AR7240_PORT_STATUS_RXFLOW); 
     888        switch (status & AR7240_PORT_STATUS_SPEED_M) { 
     889        case AR7240_PORT_STATUS_SPEED_10: 
     890                link->speed = SWITCH_PORT_SPEED_10; 
     891                break; 
     892        case AR7240_PORT_STATUS_SPEED_100: 
     893                link->speed = SWITCH_PORT_SPEED_100; 
     894                break; 
     895        case AR7240_PORT_STATUS_SPEED_1000: 
     896                link->speed = SWITCH_PORT_SPEED_1000; 
     897                break; 
     898        } 
     899 
     900        return 0; 
     901} 
     902 
     903static int 
     904ar7240_get_port_stats(struct switch_dev *dev, int port, 
     905                      struct switch_port_stats *stats) 
     906{ 
     907        struct ar7240sw *as = sw_to_ar7240(dev); 
     908 
     909        if (port > AR7240_NUM_PORTS) 
     910                return -EINVAL; 
     911 
     912        ar7240sw_capture_stats(as); 
     913 
     914        read_lock(&as->stats_lock); 
     915        stats->rx_bytes = as->port_stats[port].rx_good_byte; 
     916        stats->tx_bytes = as->port_stats[port].tx_byte; 
     917        read_unlock(&as->stats_lock); 
     918 
     919        return 0; 
     920} 
     921 
    739922static struct switch_attr ar7240_globals[] = { 
    740923        { 
    741924                .type = SWITCH_TYPE_INT, 
     
    748931}; 
    749932 
    750933static struct switch_attr ar7240_port[] = { 
     934        { 
     935                .type = SWITCH_TYPE_STRING, 
     936                .name = "link", 
     937                .description = "Get port link information", 
     938                .max = 1, 
     939                .set = NULL, 
     940                .get = ar7240_port_get_link, 
     941        }, 
    751942}; 
    752943 
    753944static struct switch_attr ar7240_vlan[] = { 
     
    780971        .set_vlan_ports = ar7240_set_ports, 
    781972        .apply_config = ar7240_hw_apply, 
    782973        .reset_switch = ar7240_reset_switch, 
     974        .get_port_link = ar7240_get_port_link, 
     975        .get_port_stats = ar7240_get_port_stats, 
    783976}; 
    784977 
    785978static struct ar7240sw *ar7240_probe(struct ag71xx *ag) 
     
    8941087        ag->phy_priv = as; 
    8951088        ar7240sw_reset(as); 
    8961089 
     1090        rwlock_init(&as->stats_lock); 
    8971091        INIT_DELAYED_WORK(&ag->link_work, link_function); 
    8981092 
    8991093        return 0; 
  • target/linux/generic-2.6/config-2.6.32

    a b  
    23142314CONFIG_SUSPEND_UP_POSSIBLE=y 
    23152315CONFIG_SWAP=y 
    23162316# CONFIG_SWCONFIG is not set 
     2317# CONFIG_SWCONFIG_LEDS is not set 
    23172318# CONFIG_SYNCLINK_CS is not set 
    23182319CONFIG_SYN_COOKIES=y 
    23192320CONFIG_SYSCTL_SYSCALL_CHECK=y 
  • target/linux/generic-2.6/files/drivers/net/phy/swconfig.c

    a b  
    3333 
    3434#define SWCONFIG_DEVNAME        "switch%d" 
    3535 
     36#include "swconfig_leds.c" 
     37 
    3638MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); 
    3739MODULE_LICENSE("GPL"); 
    3840 
     
    863865        struct switch_dev *sdev; 
    864866        const int max_switches = 8 * sizeof(unsigned long); 
    865867        unsigned long in_use = 0; 
     868        int err; 
    866869        int i; 
    867870 
    868871        INIT_LIST_HEAD(&dev->dev_list); 
     
    903906        list_add(&dev->dev_list, &swdevs); 
    904907        swconfig_unlock(); 
    905908 
     909        err = swconfig_create_led_trigger(dev); 
     910        if (err) 
     911                return err; 
     912 
    906913        return 0; 
    907914} 
    908915EXPORT_SYMBOL_GPL(register_switch); 
     
    910917void 
    911918unregister_switch(struct switch_dev *dev) 
    912919{ 
     920        swconfig_destroy_led_trigger(dev); 
    913921        kfree(dev->portbuf); 
    914922        spin_lock(&dev->lock); 
    915923        swconfig_lock(); 
  • target/linux/generic-2.6/files/drivers/net/phy/swconfig_leds.c

    a b  
     1/* 
     2 * swconfig_led.c: LED trigger support for the switch configuration API 
     3 * 
     4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> 
     5 * 
     6 * This program is free software; you can redistribute it and/or 
     7 * modify it under the terms of the GNU General Public License 
     8 * as published by the Free Software Foundation; either version 2 
     9 * of the License, or (at your option) any later version. 
     10 * 
     11 */ 
     12 
     13#ifdef CONFIG_SWCONFIG_LEDS 
     14 
     15#include <linux/leds.h> 
     16#include <linux/ctype.h> 
     17#include <linux/device.h> 
     18#include <linux/workqueue.h> 
     19 
     20#define SWCONFIG_LED_TIMER_INTERVAL     (HZ / 10) 
     21#define SWCONFIG_LED_NUM_PORTS          32 
     22 
     23struct switch_led_trigger { 
     24        struct led_trigger trig; 
     25        struct switch_dev *swdev; 
     26 
     27        struct delayed_work sw_led_work; 
     28        u32 port_mask; 
     29        u32 port_link; 
     30        unsigned long port_traffic[SWCONFIG_LED_NUM_PORTS]; 
     31}; 
     32 
     33struct swconfig_trig_data { 
     34        struct led_classdev *led_cdev; 
     35        struct switch_dev *swdev; 
     36 
     37        rwlock_t lock; 
     38        u32 port_mask; 
     39 
     40        bool prev_link; 
     41        unsigned long prev_traffic; 
     42        enum led_brightness prev_brightness; 
     43}; 
     44 
     45static void 
     46led_brightness_set(struct led_classdev *led_cdev, 
     47                   enum led_brightness brightness) 
     48{ 
     49        led_cdev->brightness = brightness; 
     50        led_cdev->brightness_set(led_cdev, brightness); 
     51} 
     52 
     53static void 
     54swconfig_trig_set_brightness(struct swconfig_trig_data *trig_data, 
     55                             enum led_brightness brightness) 
     56{ 
     57        led_brightness_set(trig_data->led_cdev, brightness); 
     58        trig_data->prev_brightness = brightness; 
     59} 
     60 
     61static void 
     62swconfig_trig_update_port_mask(struct led_trigger *trigger) 
     63{ 
     64        struct list_head *entry; 
     65        struct switch_led_trigger *sw_trig; 
     66        u32 port_mask; 
     67 
     68        if (!trigger) 
     69                return; 
     70 
     71        sw_trig = (void *) trigger; 
     72 
     73        port_mask = 0; 
     74        read_lock(&trigger->leddev_list_lock); 
     75        list_for_each(entry, &trigger->led_cdevs) { 
     76                struct led_classdev *led_cdev; 
     77                struct swconfig_trig_data *trig_data; 
     78 
     79                led_cdev = list_entry(entry, struct led_classdev, trig_list); 
     80                trig_data = led_cdev->trigger_data; 
     81                if (trig_data) { 
     82                        read_lock(&trig_data->lock); 
     83                        port_mask |= trig_data->port_mask; 
     84                        read_unlock(&trig_data->lock); 
     85                } 
     86        } 
     87        read_unlock(&trigger->leddev_list_lock); 
     88 
     89        sw_trig->port_mask = port_mask; 
     90 
     91        if (port_mask) 
     92                schedule_delayed_work(&sw_trig->sw_led_work, 
     93                                      SWCONFIG_LED_TIMER_INTERVAL); 
     94        else 
     95                cancel_delayed_work_sync(&sw_trig->sw_led_work); 
     96} 
     97 
     98static ssize_t 
     99swconfig_trig_port_mask_store(struct device *dev, struct device_attribute *attr, 
     100                              const char *buf, size_t size) 
     101{ 
     102        struct led_classdev *led_cdev = dev_get_drvdata(dev); 
     103        struct swconfig_trig_data *trig_data = led_cdev->trigger_data; 
     104        unsigned long port_mask; 
     105        ssize_t ret = -EINVAL; 
     106        char *after; 
     107        size_t count; 
     108 
     109        port_mask = simple_strtoul(buf, &after, 16); 
     110        count = after - buf; 
     111 
     112        if (*after && isspace(*after)) 
     113                count++; 
     114 
     115        if (count == size) { 
     116                bool changed; 
     117 
     118                write_lock(&trig_data->lock); 
     119 
     120                changed = (trig_data->port_mask != port_mask); 
     121                if (changed) { 
     122                        trig_data->port_mask = port_mask; 
     123                        if (port_mask == 0) 
     124                                swconfig_trig_set_brightness(trig_data, LED_OFF); 
     125                } 
     126 
     127                write_unlock(&trig_data->lock); 
     128 
     129                if (changed) 
     130                        swconfig_trig_update_port_mask(led_cdev->trigger); 
     131 
     132                ret = count; 
     133        } 
     134 
     135        return ret; 
     136} 
     137 
     138static ssize_t 
     139swconfig_trig_port_mask_show(struct device *dev, struct device_attribute *attr, 
     140                             char *buf) 
     141{ 
     142        struct led_classdev *led_cdev = dev_get_drvdata(dev); 
     143        struct swconfig_trig_data *trig_data = led_cdev->trigger_data; 
     144 
     145        read_lock(&trig_data->lock); 
     146        sprintf(buf, "%#x\n", trig_data->port_mask); 
     147        read_unlock(&trig_data->lock); 
     148 
     149        return strlen(buf) + 1; 
     150} 
     151 
     152static DEVICE_ATTR(port_mask, 0644, swconfig_trig_port_mask_show, 
     153                   swconfig_trig_port_mask_store); 
     154 
     155static void 
     156swconfig_trig_activate(struct led_classdev *led_cdev) 
     157{ 
     158        struct switch_led_trigger *sw_trig; 
     159        struct swconfig_trig_data *trig_data; 
     160        int err; 
     161 
     162        if (led_cdev->trigger->activate != swconfig_trig_activate) 
     163                return; 
     164 
     165        trig_data = kzalloc(sizeof(struct swconfig_trig_data), GFP_KERNEL); 
     166        if (!trig_data) 
     167                return; 
     168 
     169        sw_trig = (void *) led_cdev->trigger; 
     170 
     171        rwlock_init(&trig_data->lock); 
     172        trig_data->led_cdev = led_cdev; 
     173        trig_data->swdev = sw_trig->swdev; 
     174        led_cdev->trigger_data = trig_data; 
     175 
     176        err = device_create_file(led_cdev->dev, &dev_attr_port_mask); 
     177        if (err) 
     178                goto err_free; 
     179 
     180        return; 
     181 
     182err_free: 
     183        led_cdev->trigger_data = NULL; 
     184        kfree(trig_data); 
     185} 
     186 
     187static void 
     188swconfig_trig_deactivate(struct led_classdev *led_cdev) 
     189{ 
     190        struct swconfig_trig_data *trig_data; 
     191 
     192        swconfig_trig_update_port_mask(led_cdev->trigger); 
     193 
     194        trig_data = (void *) led_cdev->trigger_data; 
     195        if (trig_data) { 
     196                device_remove_file(led_cdev->dev, &dev_attr_port_mask); 
     197                kfree(trig_data); 
     198        } 
     199} 
     200 
     201static void 
     202swconfig_trig_led_event(struct switch_led_trigger *sw_trig, 
     203                        struct led_classdev *led_cdev) 
     204{ 
     205        struct swconfig_trig_data *trig_data; 
     206        u32 port_mask; 
     207        bool link; 
     208 
     209        trig_data = led_cdev->trigger_data; 
     210        if (!trig_data) 
     211                return; 
     212 
     213        read_lock(&trig_data->lock); 
     214        port_mask = trig_data->port_mask; 
     215        read_unlock(&trig_data->lock); 
     216 
     217        link = !!(sw_trig->port_link & port_mask); 
     218        if (!link) { 
     219                if (link != trig_data->prev_link) 
     220                        led_brightness_set(trig_data->led_cdev, LED_OFF); 
     221        } else { 
     222                unsigned long traffic; 
     223                int i; 
     224 
     225                traffic = 0; 
     226                for (i = 0; i < SWCONFIG_LED_NUM_PORTS; i++) { 
     227                        if (port_mask & (1 << i)) 
     228                                traffic += sw_trig->port_traffic[i]; 
     229                } 
     230 
     231                if (trig_data->prev_brightness != LED_FULL) 
     232                        swconfig_trig_set_brightness(trig_data, LED_FULL); 
     233                else if (traffic != trig_data->prev_traffic) 
     234                        swconfig_trig_set_brightness(trig_data, LED_OFF); 
     235 
     236                trig_data->prev_traffic = traffic; 
     237        } 
     238 
     239        trig_data->prev_link = link; 
     240} 
     241 
     242static void 
     243swconfig_trig_update_leds(struct switch_led_trigger *sw_trig) 
     244{ 
     245        struct list_head *entry; 
     246        struct led_trigger *trigger; 
     247 
     248        trigger = &sw_trig->trig; 
     249        read_lock(&trigger->leddev_list_lock); 
     250        list_for_each(entry, &trigger->led_cdevs) { 
     251                struct led_classdev *led_cdev; 
     252 
     253                led_cdev = list_entry(entry, struct led_classdev, trig_list); 
     254                swconfig_trig_led_event(sw_trig, led_cdev); 
     255        } 
     256        read_unlock(&trigger->leddev_list_lock); 
     257} 
     258 
     259static void 
     260swconfig_led_work_func(struct work_struct *work) 
     261{ 
     262        struct switch_led_trigger *sw_trig; 
     263        struct switch_dev *swdev; 
     264        u32 port_mask; 
     265        u32 link; 
     266        int i; 
     267 
     268        sw_trig = container_of(work, struct switch_led_trigger, 
     269                               sw_led_work.work); 
     270 
     271        port_mask = sw_trig->port_mask; 
     272        swdev = sw_trig->swdev; 
     273 
     274        link = 0; 
     275        for (i = 0; i < SWCONFIG_LED_NUM_PORTS; i++) { 
     276                u32 port_bit; 
     277 
     278                port_bit = BIT(i); 
     279                if ((port_mask & port_bit) == 0) 
     280                        continue; 
     281 
     282                if (swdev->ops->get_port_link) { 
     283                        struct switch_port_link port_link; 
     284 
     285                        memset(&port_link, '\0', sizeof(port_link)); 
     286                        swdev->ops->get_port_link(swdev, i, &port_link); 
     287 
     288                        if (port_link.link) 
     289                                link |= port_bit; 
     290                } 
     291 
     292                if (swdev->ops->get_port_stats) { 
     293                        struct switch_port_stats port_stats; 
     294 
     295                        memset(&port_stats, '\0', sizeof(port_stats)); 
     296                        swdev->ops->get_port_stats(swdev, i, &port_stats); 
     297                        sw_trig->port_traffic[i] = port_stats.tx_bytes + 
     298                                                   port_stats.rx_bytes; 
     299                } 
     300        } 
     301 
     302        sw_trig->port_link = link; 
     303 
     304        swconfig_trig_update_leds(sw_trig); 
     305 
     306        schedule_delayed_work(&sw_trig->sw_led_work, 
     307                              SWCONFIG_LED_TIMER_INTERVAL); 
     308} 
     309 
     310static int 
     311swconfig_create_led_trigger(struct switch_dev *swdev) 
     312{ 
     313        struct switch_led_trigger *sw_trig; 
     314        int err; 
     315 
     316        if (!swdev->ops->get_port_link) 
     317                return 0; 
     318 
     319        sw_trig = kzalloc(sizeof(struct switch_led_trigger), GFP_KERNEL); 
     320        if (!sw_trig) 
     321                return -ENOMEM; 
     322 
     323        sw_trig->swdev = swdev; 
     324        sw_trig->trig.name = swdev->devname; 
     325        sw_trig->trig.activate = swconfig_trig_activate; 
     326        sw_trig->trig.deactivate = swconfig_trig_deactivate; 
     327 
     328        INIT_DELAYED_WORK(&sw_trig->sw_led_work, swconfig_led_work_func); 
     329 
     330        err = led_trigger_register(&sw_trig->trig); 
     331        if (err) 
     332                goto err_free; 
     333 
     334        swdev->led_trigger = sw_trig; 
     335 
     336        return 0; 
     337 
     338err_free: 
     339        kfree(sw_trig); 
     340        return err; 
     341} 
     342 
     343static void 
     344swconfig_destroy_led_trigger(struct switch_dev *swdev) 
     345{ 
     346        struct switch_led_trigger *sw_trig; 
     347 
     348        sw_trig = swdev->led_trigger; 
     349        if (sw_trig) { 
     350                cancel_delayed_work_sync(&sw_trig->sw_led_work); 
     351                led_trigger_unregister(&sw_trig->trig); 
     352                kfree(sw_trig); 
     353        } 
     354} 
     355 
     356#else /* SWCONFIG_LEDS */ 
     357static inline int 
     358swconfig_create_led_trigger(struct switch_dev *swdev) { return 0; } 
     359 
     360static inline void 
     361swconfig_destroy_led_trigger(struct switch_dev *swdev) { } 
     362#endif /* CONFIG_SWCONFIG_LEDS */ 
  • target/linux/generic-2.6/files/include/linux/switch.h

    a b  
    9999struct switch_val; 
    100100struct switch_attr; 
    101101struct switch_attrlist; 
     102struct switch_led_trigger; 
    102103 
    103104int register_switch(struct switch_dev *dev, struct net_device *netdev); 
    104105void unregister_switch(struct switch_dev *dev); 
     
    114115        const struct switch_attr *attr; 
    115116}; 
    116117 
     118enum switch_port_speed { 
     119        SWITCH_PORT_SPEED_UNKNOWN = 0, 
     120        SWITCH_PORT_SPEED_10 = 10, 
     121        SWITCH_PORT_SPEED_100 = 100, 
     122        SWITCH_PORT_SPEED_1000 = 1000, 
     123}; 
     124 
     125struct switch_port_link { 
     126        bool link; 
     127        bool duplex; 
     128        bool aneg; 
     129        bool tx_flow; 
     130        bool rx_flow; 
     131        enum switch_port_speed speed; 
     132}; 
     133 
     134struct switch_port_stats { 
     135        unsigned long tx_bytes; 
     136        unsigned long rx_bytes; 
     137}; 
     138 
    117139/** 
    118140 * struct switch_dev_ops - switch driver operations 
    119141 * 
     
    143165 
    144166        int (*apply_config)(struct switch_dev *dev); 
    145167        int (*reset_switch)(struct switch_dev *dev); 
     168 
     169        int (*get_port_link)(struct switch_dev *dev, int port, 
     170                             struct switch_port_link *link); 
     171        int (*get_port_stats)(struct switch_dev *dev, int port, 
     172                              struct switch_port_stats *stats); 
    146173}; 
    147174 
    148175struct switch_dev { 
     
    166193 
    167194        spinlock_t lock; 
    168195        struct switch_port *portbuf; 
     196 
     197#ifdef CONFIG_SWCONFIG_LEDS 
     198        struct switch_led_trigger *led_trigger; 
     199#endif 
    169200}; 
    170201 
    171202struct switch_port { 
  • target/linux/generic-2.6/patches-2.6.32/650-swconfig.patch

    a b  
    11--- a/drivers/net/phy/Kconfig 
    22+++ b/drivers/net/phy/Kconfig 
    3 @@ -13,6 +13,12 @@ menuconfig PHYLIB 
     3@@ -13,6 +13,16 @@ menuconfig PHYLIB 
    44  
    55 if PHYLIB 
    66  
     
    1010+         Switch configuration API using netlink. This allows 
    1111+         you to configure the VLAN features of certain switches. 
    1212+ 
     13+config SWCONFIG_LEDS 
     14+       bool "Switch LED trigger support" 
     15+       depends on (SWCONFIG && LEDS_TRIGGERS) 
     16+ 
    1317 comment "MII PHY device drivers" 
    1418  
    1519 config MARVELL_PHY