aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_eeprom.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_eeprom.c303
1 files changed, 268 insertions, 35 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
index 030185f90ee2..6b9147964a4f 100644
--- a/drivers/infiniband/hw/ipath/ipath_eeprom.c
+++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2006 QLogic, Inc. All rights reserved. 2 * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
3 * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. 3 * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
4 * 4 *
5 * This software is available to you under a choice of one of two 5 * This software is available to you under a choice of one of two
@@ -95,39 +95,37 @@ static int i2c_gpio_set(struct ipath_devdata *dd,
95 enum i2c_type line, 95 enum i2c_type line,
96 enum i2c_state new_line_state) 96 enum i2c_state new_line_state)
97{ 97{
98 u64 read_val, write_val, mask, *gpioval; 98 u64 out_mask, dir_mask, *gpioval;
99 unsigned long flags = 0;
99 100
100 gpioval = &dd->ipath_gpio_out; 101 gpioval = &dd->ipath_gpio_out;
101 read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
102 if (line == i2c_line_scl)
103 mask = dd->ipath_gpio_scl;
104 else
105 mask = dd->ipath_gpio_sda;
106 102
107 if (new_line_state == i2c_line_high) 103 if (line == i2c_line_scl) {
104 dir_mask = dd->ipath_gpio_scl;
105 out_mask = (1UL << dd->ipath_gpio_scl_num);
106 } else {
107 dir_mask = dd->ipath_gpio_sda;
108 out_mask = (1UL << dd->ipath_gpio_sda_num);
109 }
110
111 spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
112 if (new_line_state == i2c_line_high) {
108 /* tri-state the output rather than force high */ 113 /* tri-state the output rather than force high */
109 write_val = read_val & ~mask; 114 dd->ipath_extctrl &= ~dir_mask;
110 else 115 } else {
111 /* config line to be an output */ 116 /* config line to be an output */
112 write_val = read_val | mask; 117 dd->ipath_extctrl |= dir_mask;
113 ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val); 118 }
119 ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl);
114 120
115 /* set high and verify */ 121 /* set output as well (no real verify) */
116 if (new_line_state == i2c_line_high) 122 if (new_line_state == i2c_line_high)
117 write_val = 0x1UL; 123 *gpioval |= out_mask;
118 else 124 else
119 write_val = 0x0UL; 125 *gpioval &= ~out_mask;
120 126
121 if (line == i2c_line_scl) {
122 write_val <<= dd->ipath_gpio_scl_num;
123 *gpioval = *gpioval & ~(1UL << dd->ipath_gpio_scl_num);
124 *gpioval |= write_val;
125 } else {
126 write_val <<= dd->ipath_gpio_sda_num;
127 *gpioval = *gpioval & ~(1UL << dd->ipath_gpio_sda_num);
128 *gpioval |= write_val;
129 }
130 ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval); 127 ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval);
128 spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
131 129
132 return 0; 130 return 0;
133} 131}
@@ -145,8 +143,9 @@ static int i2c_gpio_get(struct ipath_devdata *dd,
145 enum i2c_type line, 143 enum i2c_type line,
146 enum i2c_state *curr_statep) 144 enum i2c_state *curr_statep)
147{ 145{
148 u64 read_val, write_val, mask; 146 u64 read_val, mask;
149 int ret; 147 int ret;
148 unsigned long flags = 0;
150 149
151 /* check args */ 150 /* check args */
152 if (curr_statep == NULL) { 151 if (curr_statep == NULL) {
@@ -154,15 +153,21 @@ static int i2c_gpio_get(struct ipath_devdata *dd,
154 goto bail; 153 goto bail;
155 } 154 }
156 155
157 read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
158 /* config line to be an input */ 156 /* config line to be an input */
159 if (line == i2c_line_scl) 157 if (line == i2c_line_scl)
160 mask = dd->ipath_gpio_scl; 158 mask = dd->ipath_gpio_scl;
161 else 159 else
162 mask = dd->ipath_gpio_sda; 160 mask = dd->ipath_gpio_sda;
163 write_val = read_val & ~mask; 161
164 ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val); 162 spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
163 dd->ipath_extctrl &= ~mask;
164 ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl);
165 /*
166 * Below is very unlikely to reflect true input state if Output
167 * Enable actually changed.
168 */
165 read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus); 169 read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
170 spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
166 171
167 if (read_val & mask) 172 if (read_val & mask)
168 *curr_statep = i2c_line_high; 173 *curr_statep = i2c_line_high;
@@ -192,6 +197,7 @@ static void i2c_wait_for_writes(struct ipath_devdata *dd)
192 197
193static void scl_out(struct ipath_devdata *dd, u8 bit) 198static void scl_out(struct ipath_devdata *dd, u8 bit)
194{ 199{
200 udelay(1);
195 i2c_gpio_set(dd, i2c_line_scl, bit ? i2c_line_high : i2c_line_low); 201 i2c_gpio_set(dd, i2c_line_scl, bit ? i2c_line_high : i2c_line_low);
196 202
197 i2c_wait_for_writes(dd); 203 i2c_wait_for_writes(dd);
@@ -314,12 +320,18 @@ static int eeprom_reset(struct ipath_devdata *dd)
314 int clock_cycles_left = 9; 320 int clock_cycles_left = 9;
315 u64 *gpioval = &dd->ipath_gpio_out; 321 u64 *gpioval = &dd->ipath_gpio_out;
316 int ret; 322 int ret;
323 unsigned long flags;
317 324
318 eeprom_init = 1; 325 spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
326 /* Make sure shadows are consistent */
327 dd->ipath_extctrl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
319 *gpioval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_out); 328 *gpioval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_out);
329 spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
330
320 ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg " 331 ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg "
321 "is %llx\n", (unsigned long long) *gpioval); 332 "is %llx\n", (unsigned long long) *gpioval);
322 333
334 eeprom_init = 1;
323 /* 335 /*
324 * This is to get the i2c into a known state, by first going low, 336 * This is to get the i2c into a known state, by first going low,
325 * then tristate sda (and then tristate scl as first thing 337 * then tristate sda (and then tristate scl as first thing
@@ -355,8 +367,8 @@ bail:
355 * @len: number of bytes to receive 367 * @len: number of bytes to receive
356 */ 368 */
357 369
358int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset, 370static int ipath_eeprom_internal_read(struct ipath_devdata *dd,
359 void *buffer, int len) 371 u8 eeprom_offset, void *buffer, int len)
360{ 372{
361 /* compiler complains unless initialized */ 373 /* compiler complains unless initialized */
362 u8 single_byte = 0; 374 u8 single_byte = 0;
@@ -406,6 +418,7 @@ bail:
406 return ret; 418 return ret;
407} 419}
408 420
421
409/** 422/**
410 * ipath_eeprom_write - writes data to the eeprom via I2C 423 * ipath_eeprom_write - writes data to the eeprom via I2C
411 * @dd: the infinipath device 424 * @dd: the infinipath device
@@ -413,8 +426,8 @@ bail:
413 * @buffer: data to write 426 * @buffer: data to write
414 * @len: number of bytes to write 427 * @len: number of bytes to write
415 */ 428 */
416int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset, 429int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offset,
417 const void *buffer, int len) 430 const void *buffer, int len)
418{ 431{
419 u8 single_byte; 432 u8 single_byte;
420 int sub_len; 433 int sub_len;
@@ -488,6 +501,38 @@ bail:
488 return ret; 501 return ret;
489} 502}
490 503
504/*
505 * The public entry-points ipath_eeprom_read() and ipath_eeprom_write()
506 * are now just wrappers around the internal functions.
507 */
508int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
509 void *buff, int len)
510{
511 int ret;
512
513 ret = down_interruptible(&dd->ipath_eep_sem);
514 if (!ret) {
515 ret = ipath_eeprom_internal_read(dd, eeprom_offset, buff, len);
516 up(&dd->ipath_eep_sem);
517 }
518
519 return ret;
520}
521
522int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
523 const void *buff, int len)
524{
525 int ret;
526
527 ret = down_interruptible(&dd->ipath_eep_sem);
528 if (!ret) {
529 ret = ipath_eeprom_internal_write(dd, eeprom_offset, buff, len);
530 up(&dd->ipath_eep_sem);
531 }
532
533 return ret;
534}
535
491static u8 flash_csum(struct ipath_flash *ifp, int adjust) 536static u8 flash_csum(struct ipath_flash *ifp, int adjust)
492{ 537{
493 u8 *ip = (u8 *) ifp; 538 u8 *ip = (u8 *) ifp;
@@ -515,7 +560,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
515 void *buf; 560 void *buf;
516 struct ipath_flash *ifp; 561 struct ipath_flash *ifp;
517 __be64 guid; 562 __be64 guid;
518 int len; 563 int len, eep_stat;
519 u8 csum, *bguid; 564 u8 csum, *bguid;
520 int t = dd->ipath_unit; 565 int t = dd->ipath_unit;
521 struct ipath_devdata *dd0 = ipath_lookup(0); 566 struct ipath_devdata *dd0 = ipath_lookup(0);
@@ -559,7 +604,11 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
559 goto bail; 604 goto bail;
560 } 605 }
561 606
562 if (ipath_eeprom_read(dd, 0, buf, len)) { 607 down(&dd->ipath_eep_sem);
608 eep_stat = ipath_eeprom_internal_read(dd, 0, buf, len);
609 up(&dd->ipath_eep_sem);
610
611 if (eep_stat) {
563 ipath_dev_err(dd, "Failed reading GUID from eeprom\n"); 612 ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
564 goto done; 613 goto done;
565 } 614 }
@@ -634,8 +683,192 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
634 ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n", 683 ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n",
635 (unsigned long long) be64_to_cpu(dd->ipath_guid)); 684 (unsigned long long) be64_to_cpu(dd->ipath_guid));
636 685
686 memcpy(&dd->ipath_eep_st_errs, &ifp->if_errcntp, IPATH_EEP_LOG_CNT);
687 /*
688 * Power-on (actually "active") hours are kept as little-endian value
689 * in EEPROM, but as seconds in a (possibly as small as 24-bit)
690 * atomic_t while running.
691 */
692 atomic_set(&dd->ipath_active_time, 0);
693 dd->ipath_eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8);
694
637done: 695done:
638 vfree(buf); 696 vfree(buf);
639 697
640bail:; 698bail:;
641} 699}
700
701/**
702 * ipath_update_eeprom_log - copy active-time and error counters to eeprom
703 * @dd: the infinipath device
704 *
705 * Although the time is kept as seconds in the ipath_devdata struct, it is
706 * rounded to hours for re-write, as we have only 16 bits in EEPROM.
707 * First-cut code reads whole (expected) struct ipath_flash, modifies,
708 * re-writes. Future direction: read/write only what we need, assuming
709 * that the EEPROM had to have been "good enough" for driver init, and
710 * if not, we aren't making it worse.
711 *
712 */
713
714int ipath_update_eeprom_log(struct ipath_devdata *dd)
715{
716 void *buf;
717 struct ipath_flash *ifp;
718 int len, hi_water;
719 uint32_t new_time, new_hrs;
720 u8 csum;
721 int ret, idx;
722 unsigned long flags;
723
724 /* first, check if we actually need to do anything. */
725 ret = 0;
726 for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
727 if (dd->ipath_eep_st_new_errs[idx]) {
728 ret = 1;
729 break;
730 }
731 }
732 new_time = atomic_read(&dd->ipath_active_time);
733
734 if (ret == 0 && new_time < 3600)
735 return 0;
736
737 /*
738 * The quick-check above determined that there is something worthy
739 * of logging, so get current contents and do a more detailed idea.
740 */
741 len = offsetof(struct ipath_flash, if_future);
742 buf = vmalloc(len);
743 ret = 1;
744 if (!buf) {
745 ipath_dev_err(dd, "Couldn't allocate memory to read %u "
746 "bytes from eeprom for logging\n", len);
747 goto bail;
748 }
749
750 /* Grab semaphore and read current EEPROM. If we get an
751 * error, let go, but if not, keep it until we finish write.
752 */
753 ret = down_interruptible(&dd->ipath_eep_sem);
754 if (ret) {
755 ipath_dev_err(dd, "Unable to acquire EEPROM for logging\n");
756 goto free_bail;
757 }
758 ret = ipath_eeprom_internal_read(dd, 0, buf, len);
759 if (ret) {
760 up(&dd->ipath_eep_sem);
761 ipath_dev_err(dd, "Unable read EEPROM for logging\n");
762 goto free_bail;
763 }
764 ifp = (struct ipath_flash *)buf;
765
766 csum = flash_csum(ifp, 0);
767 if (csum != ifp->if_csum) {
768 up(&dd->ipath_eep_sem);
769 ipath_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
770 csum, ifp->if_csum);
771 ret = 1;
772 goto free_bail;
773 }
774 hi_water = 0;
775 spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
776 for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
777 int new_val = dd->ipath_eep_st_new_errs[idx];
778 if (new_val) {
779 /*
780 * If we have seen any errors, add to EEPROM values
781 * We need to saturate at 0xFF (255) and we also
782 * would need to adjust the checksum if we were
783 * trying to minimize EEPROM traffic
784 * Note that we add to actual current count in EEPROM,
785 * in case it was altered while we were running.
786 */
787 new_val += ifp->if_errcntp[idx];
788 if (new_val > 0xFF)
789 new_val = 0xFF;
790 if (ifp->if_errcntp[idx] != new_val) {
791 ifp->if_errcntp[idx] = new_val;
792 hi_water = offsetof(struct ipath_flash,
793 if_errcntp) + idx;
794 }
795 /*
796 * update our shadow (used to minimize EEPROM
797 * traffic), to match what we are about to write.
798 */
799 dd->ipath_eep_st_errs[idx] = new_val;
800 dd->ipath_eep_st_new_errs[idx] = 0;
801 }
802 }
803 /*
804 * now update active-time. We would like to round to the nearest hour
805 * but unless atomic_t are sure to be proper signed ints we cannot,
806 * because we need to account for what we "transfer" to EEPROM and
807 * if we log an hour at 31 minutes, then we would need to set
808 * active_time to -29 to accurately count the _next_ hour.
809 */
810 if (new_time > 3600) {
811 new_hrs = new_time / 3600;
812 atomic_sub((new_hrs * 3600), &dd->ipath_active_time);
813 new_hrs += dd->ipath_eep_hrs;
814 if (new_hrs > 0xFFFF)
815 new_hrs = 0xFFFF;
816 dd->ipath_eep_hrs = new_hrs;
817 if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) {
818 ifp->if_powerhour[0] = new_hrs & 0xFF;
819 hi_water = offsetof(struct ipath_flash, if_powerhour);
820 }
821 if ((new_hrs >> 8) != ifp->if_powerhour[1]) {
822 ifp->if_powerhour[1] = new_hrs >> 8;
823 hi_water = offsetof(struct ipath_flash, if_powerhour)
824 + 1;
825 }
826 }
827 /*
828 * There is a tiny possibility that we could somehow fail to write
829 * the EEPROM after updating our shadows, but problems from holding
830 * the spinlock too long are a much bigger issue.
831 */
832 spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
833 if (hi_water) {
834 /* we made some change to the data, uopdate cksum and write */
835 csum = flash_csum(ifp, 1);
836 ret = ipath_eeprom_internal_write(dd, 0, buf, hi_water + 1);
837 }
838 up(&dd->ipath_eep_sem);
839 if (ret)
840 ipath_dev_err(dd, "Failed updating EEPROM\n");
841
842free_bail:
843 vfree(buf);
844bail:
845 return ret;
846
847}
848
849/**
850 * ipath_inc_eeprom_err - increment one of the four error counters
851 * that are logged to EEPROM.
852 * @dd: the infinipath device
853 * @eidx: 0..3, the counter to increment
854 * @incr: how much to add
855 *
856 * Each counter is 8-bits, and saturates at 255 (0xFF). They
857 * are copied to the EEPROM (aka flash) whenever ipath_update_eeprom_log()
858 * is called, but it can only be called in a context that allows sleep.
859 * This function can be called even at interrupt level.
860 */
861
862void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr)
863{
864 uint new_val;
865 unsigned long flags;
866
867 spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
868 new_val = dd->ipath_eep_st_new_errs[eidx] + incr;
869 if (new_val > 255)
870 new_val = 255;
871 dd->ipath_eep_st_new_errs[eidx] = new_val;
872 spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
873 return;
874}