aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorandrew.vasquez@qlogic.com <andrew.vasquez@qlogic.com>2006-01-31 19:05:07 -0500
committer <jejb@mulgrave.il.steeleye.com>2006-02-04 17:11:57 -0500
commitf6df144cca19cc60dda6dcce65d236b70cc46494 (patch)
tree2cd4ae47df5808e46e0387c44ff436879b0e0111 /drivers/scsi/qla2xxx
parent392e2f651c8a83484116a407a9f121e534c22b5a (diff)
[SCSI] qla2xxx: Add beacon support via class-device attribute.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c50
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h21
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h9
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c294
5 files changed, 387 insertions, 3 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 5a8d5c4c69ba..049e5cf1af7f 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -196,6 +196,9 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
196 196
197 sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); 197 sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
198 sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); 198 sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
199
200 if (ha->beacon_blink_led == 1)
201 ha->isp_ops.beacon_off(ha);
199} 202}
200 203
201/* Scsi_Host attributes. */ 204/* Scsi_Host attributes. */
@@ -383,6 +386,50 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
383 return strlen(buf); 386 return strlen(buf);
384} 387}
385 388
389static ssize_t
390qla2x00_beacon_show(struct class_device *cdev, char *buf)
391{
392 scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
393 int len = 0;
394
395 if (ha->beacon_blink_led)
396 len += snprintf(buf + len, PAGE_SIZE-len, "Enabled\n");
397 else
398 len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
399 return len;
400}
401
402static ssize_t
403qla2x00_beacon_store(struct class_device *cdev, const char *buf,
404 size_t count)
405{
406 scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
407 int val = 0;
408 int rval;
409
410 if (IS_QLA2100(ha) || IS_QLA2200(ha))
411 return -EPERM;
412
413 if (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) {
414 qla_printk(KERN_WARNING, ha,
415 "Abort ISP active -- ignoring beacon request.\n");
416 return -EBUSY;
417 }
418
419 if (sscanf(buf, "%d", &val) != 1)
420 return -EINVAL;
421
422 if (val)
423 rval = ha->isp_ops.beacon_on(ha);
424 else
425 rval = ha->isp_ops.beacon_off(ha);
426
427 if (rval != QLA_SUCCESS)
428 count = 0;
429
430 return count;
431}
432
386static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, 433static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
387 NULL); 434 NULL);
388static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); 435static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
@@ -397,6 +444,8 @@ static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show,
397 qla2x00_zio_store); 444 qla2x00_zio_store);
398static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, 445static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
399 qla2x00_zio_timer_store); 446 qla2x00_zio_timer_store);
447static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
448 qla2x00_beacon_store);
400 449
401struct class_device_attribute *qla2x00_host_attrs[] = { 450struct class_device_attribute *qla2x00_host_attrs[] = {
402 &class_device_attr_driver_version, 451 &class_device_attr_driver_version,
@@ -410,6 +459,7 @@ struct class_device_attribute *qla2x00_host_attrs[] = {
410 &class_device_attr_state, 459 &class_device_attr_state,
411 &class_device_attr_zio, 460 &class_device_attr_zio,
412 &class_device_attr_zio_timer, 461 &class_device_attr_zio_timer,
462 &class_device_attr_beacon,
413 NULL, 463 NULL,
414}; 464};
415 465
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 414580800dc0..7cb8b5a5e659 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -182,6 +182,13 @@
182#define WRT_REG_DWORD(addr, data) writel(data,addr) 182#define WRT_REG_DWORD(addr, data) writel(data,addr)
183 183
184/* 184/*
185 * The ISP2312 v2 chip cannot access the FLASH/GPIO registers via MMIO in an
186 * 133Mhz slot.
187 */
188#define RD_REG_WORD_PIO(addr) (inw((unsigned long)addr))
189#define WRT_REG_WORD_PIO(addr, data) (outw(data,(unsigned long)addr))
190
191/*
185 * Fibre Channel device definitions. 192 * Fibre Channel device definitions.
186 */ 193 */
187#define WWN_SIZE 8 /* Size of WWPN, WWN & WWNN */ 194#define WWN_SIZE 8 /* Size of WWPN, WWN & WWNN */
@@ -433,6 +440,9 @@ struct device_reg_2xxx {
433#define GPIO_LED_GREEN_ON_AMBER_OFF 0x0040 440#define GPIO_LED_GREEN_ON_AMBER_OFF 0x0040
434#define GPIO_LED_GREEN_OFF_AMBER_ON 0x0080 441#define GPIO_LED_GREEN_OFF_AMBER_ON 0x0080
435#define GPIO_LED_GREEN_ON_AMBER_ON 0x00C0 442#define GPIO_LED_GREEN_ON_AMBER_ON 0x00C0
443#define GPIO_LED_ALL_OFF 0x0000
444#define GPIO_LED_RED_ON_OTHER_OFF 0x0001 /* isp2322 */
445#define GPIO_LED_RGA_ON 0x00C1 /* isp2322: red green amber */
436 446
437 union { 447 union {
438 struct { 448 struct {
@@ -2200,6 +2210,10 @@ struct isp_operations {
2200 2210
2201 void (*fw_dump) (struct scsi_qla_host *, int); 2211 void (*fw_dump) (struct scsi_qla_host *, int);
2202 void (*ascii_fw_dump) (struct scsi_qla_host *); 2212 void (*ascii_fw_dump) (struct scsi_qla_host *);
2213
2214 int (*beacon_on) (struct scsi_qla_host *);
2215 int (*beacon_off) (struct scsi_qla_host *);
2216 void (*beacon_blink) (struct scsi_qla_host *);
2203}; 2217};
2204 2218
2205/* 2219/*
@@ -2493,7 +2507,12 @@ typedef struct scsi_qla_host {
2493 2507
2494 /* Needed for BEACON */ 2508 /* Needed for BEACON */
2495 uint16_t beacon_blink_led; 2509 uint16_t beacon_blink_led;
2496 uint16_t beacon_green_on; 2510 uint8_t beacon_color_state;
2511#define QLA_LED_GRN_ON 0x01
2512#define QLA_LED_YLW_ON 0x02
2513#define QLA_LED_ABR_ON 0x04
2514#define QLA_LED_ALL_ON 0x07 /* yellow, green, amber. */
2515 /* ISP2322: red, green, amber. */
2497 2516
2498 uint16_t zio_mode; 2517 uint16_t zio_mode;
2499 uint16_t zio_timer; 2518 uint16_t zio_timer;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index f2f5454a05e9..eb35198bc8cf 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -75,8 +75,6 @@ extern void qla2x00_cmd_timeout(srb_t *);
75extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int); 75extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
76extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int); 76extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
77 77
78extern void qla2x00_blink_led(scsi_qla_host_t *);
79
80extern int qla2x00_down_timeout(struct semaphore *, unsigned long); 78extern int qla2x00_down_timeout(struct semaphore *, unsigned long);
81 79
82extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); 80extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
@@ -235,6 +233,13 @@ extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
235extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, 233extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
236 uint32_t); 234 uint32_t);
237 235
236extern int qla2x00_beacon_on(struct scsi_qla_host *);
237extern int qla2x00_beacon_off(struct scsi_qla_host *);
238extern void qla2x00_beacon_blink(struct scsi_qla_host *);
239extern int qla24xx_beacon_on(struct scsi_qla_host *);
240extern int qla24xx_beacon_off(struct scsi_qla_host *);
241extern void qla24xx_beacon_blink(struct scsi_qla_host *);
242
238/* 243/*
239 * Global Function Prototypes in qla_dbg.c source file. 244 * Global Function Prototypes in qla_dbg.c source file.
240 */ 245 */
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 6e133edb2016..57179dabcccf 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1365,6 +1365,9 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1365 ha->isp_ops.intr_handler = qla2300_intr_handler; 1365 ha->isp_ops.intr_handler = qla2300_intr_handler;
1366 ha->isp_ops.fw_dump = qla2300_fw_dump; 1366 ha->isp_ops.fw_dump = qla2300_fw_dump;
1367 ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump; 1367 ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump;
1368 ha->isp_ops.beacon_on = qla2x00_beacon_on;
1369 ha->isp_ops.beacon_off = qla2x00_beacon_off;
1370 ha->isp_ops.beacon_blink = qla2x00_beacon_blink;
1368 ha->gid_list_info_size = 6; 1371 ha->gid_list_info_size = 6;
1369 } else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { 1372 } else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
1370 host->max_id = MAX_TARGETS_2200; 1373 host->max_id = MAX_TARGETS_2200;
@@ -1401,6 +1404,9 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1401 ha->isp_ops.write_nvram = qla24xx_write_nvram_data; 1404 ha->isp_ops.write_nvram = qla24xx_write_nvram_data;
1402 ha->isp_ops.fw_dump = qla24xx_fw_dump; 1405 ha->isp_ops.fw_dump = qla24xx_fw_dump;
1403 ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump; 1406 ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump;
1407 ha->isp_ops.beacon_on = qla24xx_beacon_on;
1408 ha->isp_ops.beacon_off = qla24xx_beacon_off;
1409 ha->isp_ops.beacon_blink = qla24xx_beacon_blink;
1404 ha->gid_list_info_size = 8; 1410 ha->gid_list_info_size = 8;
1405 } 1411 }
1406 host->can_queue = ha->request_q_length + 128; 1412 host->can_queue = ha->request_q_length + 128;
@@ -2315,6 +2321,9 @@ qla2x00_do_dpc(void *data)
2315 if (!ha->interrupts_on) 2321 if (!ha->interrupts_on)
2316 ha->isp_ops.enable_intrs(ha); 2322 ha->isp_ops.enable_intrs(ha);
2317 2323
2324 if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags))
2325 ha->isp_ops.beacon_blink(ha);
2326
2318 ha->dpc_active = 0; 2327 ha->dpc_active = 0;
2319 } /* End of while(1) */ 2328 } /* End of while(1) */
2320 2329
@@ -2492,6 +2501,12 @@ qla2x00_timer(scsi_qla_host_t *ha)
2492 atomic_read(&ha->loop_down_timer))); 2501 atomic_read(&ha->loop_down_timer)));
2493 } 2502 }
2494 2503
2504 /* Check if beacon LED needs to be blinked */
2505 if (ha->beacon_blink_led == 1) {
2506 set_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags);
2507 start_dpc++;
2508 }
2509
2495 /* Schedule the DPC routine if needed */ 2510 /* Schedule the DPC routine if needed */
2496 if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || 2511 if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
2497 test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || 2512 test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
@@ -2500,6 +2515,7 @@ qla2x00_timer(scsi_qla_host_t *ha)
2500 start_dpc || 2515 start_dpc ||
2501 test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || 2516 test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
2502 test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || 2517 test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
2518 test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
2503 test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) && 2519 test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) &&
2504 ha->dpc_wait && !ha->dpc_active) { 2520 ha->dpc_wait && !ha->dpc_active) {
2505 2521
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index f4d755a643e4..3105bb93cc19 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -695,3 +695,297 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
695 695
696 return ret; 696 return ret;
697} 697}
698
699
700static inline void
701qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags)
702{
703 if (IS_QLA2322(ha)) {
704 /* Flip all colors. */
705 if (ha->beacon_color_state == QLA_LED_ALL_ON) {
706 /* Turn off. */
707 ha->beacon_color_state = 0;
708 *pflags = GPIO_LED_ALL_OFF;
709 } else {
710 /* Turn on. */
711 ha->beacon_color_state = QLA_LED_ALL_ON;
712 *pflags = GPIO_LED_RGA_ON;
713 }
714 } else {
715 /* Flip green led only. */
716 if (ha->beacon_color_state == QLA_LED_GRN_ON) {
717 /* Turn off. */
718 ha->beacon_color_state = 0;
719 *pflags = GPIO_LED_GREEN_OFF_AMBER_OFF;
720 } else {
721 /* Turn on. */
722 ha->beacon_color_state = QLA_LED_GRN_ON;
723 *pflags = GPIO_LED_GREEN_ON_AMBER_OFF;
724 }
725 }
726}
727
728void
729qla2x00_beacon_blink(struct scsi_qla_host *ha)
730{
731 uint16_t gpio_enable;
732 uint16_t gpio_data;
733 uint16_t led_color = 0;
734 unsigned long flags;
735 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
736
737 if (ha->pio_address)
738 reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
739
740 spin_lock_irqsave(&ha->hardware_lock, flags);
741
742 /* Save the Original GPIOE. */
743 if (ha->pio_address) {
744 gpio_enable = RD_REG_WORD_PIO(&reg->gpioe);
745 gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
746 } else {
747 gpio_enable = RD_REG_WORD(&reg->gpioe);
748 gpio_data = RD_REG_WORD(&reg->gpiod);
749 }
750
751 /* Set the modified gpio_enable values */
752 gpio_enable |= GPIO_LED_MASK;
753
754 if (ha->pio_address) {
755 WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
756 } else {
757 WRT_REG_WORD(&reg->gpioe, gpio_enable);
758 RD_REG_WORD(&reg->gpioe);
759 }
760
761 qla2x00_flip_colors(ha, &led_color);
762
763 /* Clear out any previously set LED color. */
764 gpio_data &= ~GPIO_LED_MASK;
765
766 /* Set the new input LED color to GPIOD. */
767 gpio_data |= led_color;
768
769 /* Set the modified gpio_data values */
770 if (ha->pio_address) {
771 WRT_REG_WORD_PIO(&reg->gpiod, gpio_data);
772 } else {
773 WRT_REG_WORD(&reg->gpiod, gpio_data);
774 RD_REG_WORD(&reg->gpiod);
775 }
776
777 spin_unlock_irqrestore(&ha->hardware_lock, flags);
778}
779
780int
781qla2x00_beacon_on(struct scsi_qla_host *ha)
782{
783 uint16_t gpio_enable;
784 uint16_t gpio_data;
785 unsigned long flags;
786 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
787
788 ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
789 ha->fw_options[1] |= FO1_DISABLE_GPIO6_7;
790
791 if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
792 qla_printk(KERN_WARNING, ha,
793 "Unable to update fw options (beacon on).\n");
794 return QLA_FUNCTION_FAILED;
795 }
796
797 if (ha->pio_address)
798 reg = (struct device_reg_2xxx __iomem *)ha->pio_address;
799
800 /* Turn off LEDs. */
801 spin_lock_irqsave(&ha->hardware_lock, flags);
802 if (ha->pio_address) {
803 gpio_enable = RD_REG_WORD_PIO(&reg->gpioe);
804 gpio_data = RD_REG_WORD_PIO(&reg->gpiod);
805 } else {
806 gpio_enable = RD_REG_WORD(&reg->gpioe);
807 gpio_data = RD_REG_WORD(&reg->gpiod);
808 }
809 gpio_enable |= GPIO_LED_MASK;
810
811 /* Set the modified gpio_enable values. */
812 if (ha->pio_address) {
813 WRT_REG_WORD_PIO(&reg->gpioe, gpio_enable);
814 } else {
815 WRT_REG_WORD(&reg->gpioe, gpio_enable);
816 RD_REG_WORD(&reg->gpioe);
817 }
818
819 /* Clear out previously set LED colour. */
820 gpio_data &= ~GPIO_LED_MASK;
821 if (ha->pio_address) {
822 WRT_REG_WORD_PIO(&reg->gpiod, gpio_data);
823 } else {
824 WRT_REG_WORD(&reg->gpiod, gpio_data);
825 RD_REG_WORD(&reg->gpiod);
826 }
827 spin_unlock_irqrestore(&ha->hardware_lock, flags);
828
829 /*
830 * Let the per HBA timer kick off the blinking process based on
831 * the following flags. No need to do anything else now.
832 */
833 ha->beacon_blink_led = 1;
834 ha->beacon_color_state = 0;
835
836 return QLA_SUCCESS;
837}
838
839int
840qla2x00_beacon_off(struct scsi_qla_host *ha)
841{
842 int rval = QLA_SUCCESS;
843
844 ha->beacon_blink_led = 0;
845
846 /* Set the on flag so when it gets flipped it will be off. */
847 if (IS_QLA2322(ha))
848 ha->beacon_color_state = QLA_LED_ALL_ON;
849 else
850 ha->beacon_color_state = QLA_LED_GRN_ON;
851
852 ha->isp_ops.beacon_blink(ha); /* This turns green LED off */
853
854 ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
855 ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7;
856
857 rval = qla2x00_set_fw_options(ha, ha->fw_options);
858 if (rval != QLA_SUCCESS)
859 qla_printk(KERN_WARNING, ha,
860 "Unable to update fw options (beacon off).\n");
861 return rval;
862}
863
864
865static inline void
866qla24xx_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags)
867{
868 /* Flip all colors. */
869 if (ha->beacon_color_state == QLA_LED_ALL_ON) {
870 /* Turn off. */
871 ha->beacon_color_state = 0;
872 *pflags = 0;
873 } else {
874 /* Turn on. */
875 ha->beacon_color_state = QLA_LED_ALL_ON;
876 *pflags = GPDX_LED_YELLOW_ON | GPDX_LED_AMBER_ON;
877 }
878}
879
880void
881qla24xx_beacon_blink(struct scsi_qla_host *ha)
882{
883 uint16_t led_color = 0;
884 uint32_t gpio_data;
885 unsigned long flags;
886 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
887
888 /* Save the Original GPIOD. */
889 spin_lock_irqsave(&ha->hardware_lock, flags);
890 gpio_data = RD_REG_DWORD(&reg->gpiod);
891
892 /* Enable the gpio_data reg for update. */
893 gpio_data |= GPDX_LED_UPDATE_MASK;
894
895 WRT_REG_DWORD(&reg->gpiod, gpio_data);
896 gpio_data = RD_REG_DWORD(&reg->gpiod);
897
898 /* Set the color bits. */
899 qla24xx_flip_colors(ha, &led_color);
900
901 /* Clear out any previously set LED color. */
902 gpio_data &= ~GPDX_LED_COLOR_MASK;
903
904 /* Set the new input LED color to GPIOD. */
905 gpio_data |= led_color;
906
907 /* Set the modified gpio_data values. */
908 WRT_REG_DWORD(&reg->gpiod, gpio_data);
909 gpio_data = RD_REG_DWORD(&reg->gpiod);
910 spin_unlock_irqrestore(&ha->hardware_lock, flags);
911}
912
913int
914qla24xx_beacon_on(struct scsi_qla_host *ha)
915{
916 uint32_t gpio_data;
917 unsigned long flags;
918 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
919
920 if (ha->beacon_blink_led == 0) {
921 /* Enable firmware for update */
922 ha->fw_options[1] |= ADD_FO1_DISABLE_GPIO_LED_CTRL;
923
924 if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS)
925 return QLA_FUNCTION_FAILED;
926
927 if (qla2x00_get_fw_options(ha, ha->fw_options) !=
928 QLA_SUCCESS) {
929 qla_printk(KERN_WARNING, ha,
930 "Unable to update fw options (beacon on).\n");
931 return QLA_FUNCTION_FAILED;
932 }
933
934 spin_lock_irqsave(&ha->hardware_lock, flags);
935 gpio_data = RD_REG_DWORD(&reg->gpiod);
936
937 /* Enable the gpio_data reg for update. */
938 gpio_data |= GPDX_LED_UPDATE_MASK;
939 WRT_REG_DWORD(&reg->gpiod, gpio_data);
940 RD_REG_DWORD(&reg->gpiod);
941
942 spin_unlock_irqrestore(&ha->hardware_lock, flags);
943 }
944
945 /* So all colors blink together. */
946 ha->beacon_color_state = 0;
947
948 /* Let the per HBA timer kick off the blinking process. */
949 ha->beacon_blink_led = 1;
950
951 return QLA_SUCCESS;
952}
953
954int
955qla24xx_beacon_off(struct scsi_qla_host *ha)
956{
957 uint32_t gpio_data;
958 unsigned long flags;
959 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
960
961 ha->beacon_blink_led = 0;
962 ha->beacon_color_state = QLA_LED_ALL_ON;
963
964 ha->isp_ops.beacon_blink(ha); /* Will flip to all off. */
965
966 /* Give control back to firmware. */
967 spin_lock_irqsave(&ha->hardware_lock, flags);
968 gpio_data = RD_REG_DWORD(&reg->gpiod);
969
970 /* Disable the gpio_data reg for update. */
971 gpio_data &= ~GPDX_LED_UPDATE_MASK;
972 WRT_REG_DWORD(&reg->gpiod, gpio_data);
973 RD_REG_DWORD(&reg->gpiod);
974 spin_unlock_irqrestore(&ha->hardware_lock, flags);
975
976 ha->fw_options[1] &= ~ADD_FO1_DISABLE_GPIO_LED_CTRL;
977
978 if (qla2x00_set_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
979 qla_printk(KERN_WARNING, ha,
980 "Unable to update fw options (beacon off).\n");
981 return QLA_FUNCTION_FAILED;
982 }
983
984 if (qla2x00_get_fw_options(ha, ha->fw_options) != QLA_SUCCESS) {
985 qla_printk(KERN_WARNING, ha,
986 "Unable to get fw options (beacon off).\n");
987 return QLA_FUNCTION_FAILED;
988 }
989
990 return QLA_SUCCESS;
991}