diff options
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 92 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6110.c | 10 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6120.c | 10 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 19 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_sysfs.c | 19 |
5 files changed, 149 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index e3a223209710..097593286582 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -1846,6 +1846,87 @@ void ipath_write_kreg_port(const struct ipath_devdata *dd, ipath_kreg regno, | |||
1846 | ipath_write_kreg(dd, where, value); | 1846 | ipath_write_kreg(dd, where, value); |
1847 | } | 1847 | } |
1848 | 1848 | ||
1849 | /* | ||
1850 | * Following deal with the "obviously simple" task of overriding the state | ||
1851 | * of the LEDS, which normally indicate link physical and logical status. | ||
1852 | * The complications arise in dealing with different hardware mappings | ||
1853 | * and the board-dependent routine being called from interrupts. | ||
1854 | * and then there's the requirement to _flash_ them. | ||
1855 | */ | ||
1856 | #define LED_OVER_FREQ_SHIFT 8 | ||
1857 | #define LED_OVER_FREQ_MASK (0xFF<<LED_OVER_FREQ_SHIFT) | ||
1858 | /* Below is "non-zero" to force override, but both actual LEDs are off */ | ||
1859 | #define LED_OVER_BOTH_OFF (8) | ||
1860 | |||
1861 | void ipath_run_led_override(unsigned long opaque) | ||
1862 | { | ||
1863 | struct ipath_devdata *dd = (struct ipath_devdata *)opaque; | ||
1864 | int timeoff; | ||
1865 | int pidx; | ||
1866 | u64 lstate, ltstate, val; | ||
1867 | |||
1868 | if (!(dd->ipath_flags & IPATH_INITTED)) | ||
1869 | return; | ||
1870 | |||
1871 | pidx = dd->ipath_led_override_phase++ & 1; | ||
1872 | dd->ipath_led_override = dd->ipath_led_override_vals[pidx]; | ||
1873 | timeoff = dd->ipath_led_override_timeoff; | ||
1874 | |||
1875 | /* | ||
1876 | * below potentially restores the LED values per current status, | ||
1877 | * should also possibly setup the traffic-blink register, | ||
1878 | * but leave that to per-chip functions. | ||
1879 | */ | ||
1880 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus); | ||
1881 | ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) & | ||
1882 | INFINIPATH_IBCS_LINKTRAININGSTATE_MASK; | ||
1883 | lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) & | ||
1884 | INFINIPATH_IBCS_LINKSTATE_MASK; | ||
1885 | |||
1886 | dd->ipath_f_setextled(dd, lstate, ltstate); | ||
1887 | mod_timer(&dd->ipath_led_override_timer, jiffies + timeoff); | ||
1888 | } | ||
1889 | |||
1890 | void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val) | ||
1891 | { | ||
1892 | int timeoff, freq; | ||
1893 | |||
1894 | if (!(dd->ipath_flags & IPATH_INITTED)) | ||
1895 | return; | ||
1896 | |||
1897 | /* First check if we are blinking. If not, use 1HZ polling */ | ||
1898 | timeoff = HZ; | ||
1899 | freq = (val & LED_OVER_FREQ_MASK) >> LED_OVER_FREQ_SHIFT; | ||
1900 | |||
1901 | if (freq) { | ||
1902 | /* For blink, set each phase from one nybble of val */ | ||
1903 | dd->ipath_led_override_vals[0] = val & 0xF; | ||
1904 | dd->ipath_led_override_vals[1] = (val >> 4) & 0xF; | ||
1905 | timeoff = (HZ << 4)/freq; | ||
1906 | } else { | ||
1907 | /* Non-blink set both phases the same. */ | ||
1908 | dd->ipath_led_override_vals[0] = val & 0xF; | ||
1909 | dd->ipath_led_override_vals[1] = val & 0xF; | ||
1910 | } | ||
1911 | dd->ipath_led_override_timeoff = timeoff; | ||
1912 | |||
1913 | /* | ||
1914 | * If the timer has not already been started, do so. Use a "quick" | ||
1915 | * timeout so the function will be called soon, to look at our request. | ||
1916 | */ | ||
1917 | if (atomic_inc_return(&dd->ipath_led_override_timer_active) == 1) { | ||
1918 | /* Need to start timer */ | ||
1919 | init_timer(&dd->ipath_led_override_timer); | ||
1920 | dd->ipath_led_override_timer.function = | ||
1921 | ipath_run_led_override; | ||
1922 | dd->ipath_led_override_timer.data = (unsigned long) dd; | ||
1923 | dd->ipath_led_override_timer.expires = jiffies + 1; | ||
1924 | add_timer(&dd->ipath_led_override_timer); | ||
1925 | } else { | ||
1926 | atomic_dec(&dd->ipath_led_override_timer_active); | ||
1927 | } | ||
1928 | } | ||
1929 | |||
1849 | /** | 1930 | /** |
1850 | * ipath_shutdown_device - shut down a device | 1931 | * ipath_shutdown_device - shut down a device |
1851 | * @dd: the infinipath device | 1932 | * @dd: the infinipath device |
@@ -1909,7 +1990,6 @@ void ipath_shutdown_device(struct ipath_devdata *dd) | |||
1909 | * Turn the LEDs off explictly for the same reason. | 1990 | * Turn the LEDs off explictly for the same reason. |
1910 | */ | 1991 | */ |
1911 | dd->ipath_f_quiet_serdes(dd); | 1992 | dd->ipath_f_quiet_serdes(dd); |
1912 | dd->ipath_f_setextled(dd, 0, 0); | ||
1913 | 1993 | ||
1914 | if (dd->ipath_stats_timer_active) { | 1994 | if (dd->ipath_stats_timer_active) { |
1915 | del_timer_sync(&dd->ipath_stats_timer); | 1995 | del_timer_sync(&dd->ipath_stats_timer); |
@@ -2085,6 +2165,16 @@ int ipath_reset_device(int unit) | |||
2085 | goto bail; | 2165 | goto bail; |
2086 | } | 2166 | } |
2087 | 2167 | ||
2168 | if (atomic_read(&dd->ipath_led_override_timer_active)) { | ||
2169 | /* Need to stop LED timer, _then_ shut off LEDs */ | ||
2170 | del_timer_sync(&dd->ipath_led_override_timer); | ||
2171 | atomic_set(&dd->ipath_led_override_timer_active, 0); | ||
2172 | } | ||
2173 | |||
2174 | /* Shut off LEDs after we are sure timer is not running */ | ||
2175 | dd->ipath_led_override = LED_OVER_BOTH_OFF; | ||
2176 | dd->ipath_f_setextled(dd, 0, 0); | ||
2177 | |||
2088 | dev_info(&dd->pcidev->dev, "Reset on unit %u requested\n", unit); | 2178 | dev_info(&dd->pcidev->dev, "Reset on unit %u requested\n", unit); |
2089 | 2179 | ||
2090 | if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) { | 2180 | if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) { |
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c index ba73dd0a06cd..4372c6c50ff6 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6110.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c | |||
@@ -1065,6 +1065,16 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd, | |||
1065 | if (ipath_diag_inuse) | 1065 | if (ipath_diag_inuse) |
1066 | return; | 1066 | return; |
1067 | 1067 | ||
1068 | /* Allow override of LED display for, e.g. Locating system in rack */ | ||
1069 | if (dd->ipath_led_override) { | ||
1070 | ltst = (dd->ipath_led_override & IPATH_LED_PHYS) | ||
1071 | ? INFINIPATH_IBCS_LT_STATE_LINKUP | ||
1072 | : INFINIPATH_IBCS_LT_STATE_DISABLED; | ||
1073 | lst = (dd->ipath_led_override & IPATH_LED_LOG) | ||
1074 | ? INFINIPATH_IBCS_L_STATE_ACTIVE | ||
1075 | : INFINIPATH_IBCS_L_STATE_DOWN; | ||
1076 | } | ||
1077 | |||
1068 | /* | 1078 | /* |
1069 | * start by setting both LED control bits to off, then turn | 1079 | * start by setting both LED control bits to off, then turn |
1070 | * on the appropriate bit(s). | 1080 | * on the appropriate bit(s). |
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c index 4e2e3dfeb2c8..bcb70d67dbb9 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c | |||
@@ -797,6 +797,16 @@ static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst, | |||
797 | if (ipath_diag_inuse) | 797 | if (ipath_diag_inuse) |
798 | return; | 798 | return; |
799 | 799 | ||
800 | /* Allow override of LED display for, e.g. Locating system in rack */ | ||
801 | if (dd->ipath_led_override) { | ||
802 | ltst = (dd->ipath_led_override & IPATH_LED_PHYS) | ||
803 | ? INFINIPATH_IBCS_LT_STATE_LINKUP | ||
804 | : INFINIPATH_IBCS_LT_STATE_DISABLED; | ||
805 | lst = (dd->ipath_led_override & IPATH_LED_LOG) | ||
806 | ? INFINIPATH_IBCS_L_STATE_ACTIVE | ||
807 | : INFINIPATH_IBCS_L_STATE_DOWN; | ||
808 | } | ||
809 | |||
800 | extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON | | 810 | extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON | |
801 | INFINIPATH_EXTC_LED2PRIPORT_ON); | 811 | INFINIPATH_EXTC_LED2PRIPORT_ON); |
802 | 812 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 12194f3dd8cc..2f39db7df31c 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -575,6 +575,16 @@ struct ipath_devdata { | |||
575 | u16 ipath_gpio_scl_num; | 575 | u16 ipath_gpio_scl_num; |
576 | u64 ipath_gpio_sda; | 576 | u64 ipath_gpio_sda; |
577 | u64 ipath_gpio_scl; | 577 | u64 ipath_gpio_scl; |
578 | |||
579 | /* used to override LED behavior */ | ||
580 | u8 ipath_led_override; /* Substituted for normal value, if non-zero */ | ||
581 | u16 ipath_led_override_timeoff; /* delta to next timer event */ | ||
582 | u8 ipath_led_override_vals[2]; /* Alternates per blink-frame */ | ||
583 | u8 ipath_led_override_phase; /* Just counts, LSB picks from vals[] */ | ||
584 | atomic_t ipath_led_override_timer_active; | ||
585 | /* Used to flash LEDs in override mode */ | ||
586 | struct timer_list ipath_led_override_timer; | ||
587 | |||
578 | }; | 588 | }; |
579 | 589 | ||
580 | /* Private data for file operations */ | 590 | /* Private data for file operations */ |
@@ -717,6 +727,15 @@ u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg); | |||
717 | void ipath_disarm_senderrbufs(struct ipath_devdata *, int); | 727 | void ipath_disarm_senderrbufs(struct ipath_devdata *, int); |
718 | 728 | ||
719 | /* | 729 | /* |
730 | * Set LED override, only the two LSBs have "public" meaning, but | ||
731 | * any non-zero value substitutes them for the Link and LinkTrain | ||
732 | * LED states. | ||
733 | */ | ||
734 | #define IPATH_LED_PHYS 1 /* Physical (linktraining) GREEN LED */ | ||
735 | #define IPATH_LED_LOG 2 /* Logical (link) YELLOW LED */ | ||
736 | void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val); | ||
737 | |||
738 | /* | ||
720 | * number of words used for protocol header if not set by ipath_userinit(); | 739 | * number of words used for protocol header if not set by ipath_userinit(); |
721 | */ | 740 | */ |
722 | #define IPATH_DFLT_RCVHDRSIZE 9 | 741 | #define IPATH_DFLT_RCVHDRSIZE 9 |
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c index 4dc398d5e011..17ec14571722 100644 --- a/drivers/infiniband/hw/ipath/ipath_sysfs.c +++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c | |||
@@ -596,6 +596,23 @@ bail: | |||
596 | return ret; | 596 | return ret; |
597 | } | 597 | } |
598 | 598 | ||
599 | static ssize_t store_led_override(struct device *dev, | ||
600 | struct device_attribute *attr, | ||
601 | const char *buf, | ||
602 | size_t count) | ||
603 | { | ||
604 | struct ipath_devdata *dd = dev_get_drvdata(dev); | ||
605 | int ret; | ||
606 | u16 val; | ||
607 | |||
608 | ret = ipath_parse_ushort(buf, &val); | ||
609 | if (ret > 0) | ||
610 | ipath_set_led_override(dd, val); | ||
611 | else | ||
612 | ipath_dev_err(dd, "attempt to set invalid LED override\n"); | ||
613 | return ret; | ||
614 | } | ||
615 | |||
599 | 616 | ||
600 | static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL); | 617 | static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL); |
601 | static DRIVER_ATTR(version, S_IRUGO, show_version, NULL); | 618 | static DRIVER_ATTR(version, S_IRUGO, show_version, NULL); |
@@ -625,6 +642,7 @@ static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL); | |||
625 | static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); | 642 | static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); |
626 | static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL); | 643 | static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL); |
627 | static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv); | 644 | static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv); |
645 | static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override); | ||
628 | 646 | ||
629 | static struct attribute *dev_attributes[] = { | 647 | static struct attribute *dev_attributes[] = { |
630 | &dev_attr_guid.attr, | 648 | &dev_attr_guid.attr, |
@@ -641,6 +659,7 @@ static struct attribute *dev_attributes[] = { | |||
641 | &dev_attr_unit.attr, | 659 | &dev_attr_unit.attr, |
642 | &dev_attr_enabled.attr, | 660 | &dev_attr_enabled.attr, |
643 | &dev_attr_rx_pol_inv.attr, | 661 | &dev_attr_rx_pol_inv.attr, |
662 | &dev_attr_led_override.attr, | ||
644 | NULL | 663 | NULL |
645 | }; | 664 | }; |
646 | 665 | ||