0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <linux/delay.h>
0036 #include <linux/pci.h>
0037 #include <linux/vmalloc.h>
0038
0039 #include "qib.h"
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 int qib_eeprom_read(struct qib_devdata *dd, u8 eeprom_offset,
0054 void *buff, int len)
0055 {
0056 int ret;
0057
0058 ret = mutex_lock_interruptible(&dd->eep_lock);
0059 if (!ret) {
0060 ret = qib_twsi_reset(dd);
0061 if (ret)
0062 qib_dev_err(dd, "EEPROM Reset for read failed\n");
0063 else
0064 ret = qib_twsi_blk_rd(dd, dd->twsi_eeprom_dev,
0065 eeprom_offset, buff, len);
0066 mutex_unlock(&dd->eep_lock);
0067 }
0068
0069 return ret;
0070 }
0071
0072
0073
0074
0075
0076
0077 static int eeprom_write_with_enable(struct qib_devdata *dd, u8 offset,
0078 const void *buf, int len)
0079 {
0080 int ret, pwen;
0081
0082 pwen = dd->f_eeprom_wen(dd, 1);
0083 ret = qib_twsi_reset(dd);
0084 if (ret)
0085 qib_dev_err(dd, "EEPROM Reset for write failed\n");
0086 else
0087 ret = qib_twsi_blk_wr(dd, dd->twsi_eeprom_dev,
0088 offset, buf, len);
0089 dd->f_eeprom_wen(dd, pwen);
0090 return ret;
0091 }
0092
0093
0094
0095
0096
0097
0098
0099
0100 int qib_eeprom_write(struct qib_devdata *dd, u8 eeprom_offset,
0101 const void *buff, int len)
0102 {
0103 int ret;
0104
0105 ret = mutex_lock_interruptible(&dd->eep_lock);
0106 if (!ret) {
0107 ret = eeprom_write_with_enable(dd, eeprom_offset, buff, len);
0108 mutex_unlock(&dd->eep_lock);
0109 }
0110
0111 return ret;
0112 }
0113
0114 static u8 flash_csum(struct qib_flash *ifp, int adjust)
0115 {
0116 u8 *ip = (u8 *) ifp;
0117 u8 csum = 0, len;
0118
0119
0120
0121
0122
0123
0124 len = ifp->if_length;
0125 if (len > sizeof(struct qib_flash))
0126 len = sizeof(struct qib_flash);
0127 while (len--)
0128 csum += *ip++;
0129 csum -= ifp->if_csum;
0130 csum = ~csum;
0131 if (adjust)
0132 ifp->if_csum = csum;
0133
0134 return csum;
0135 }
0136
0137
0138
0139
0140
0141
0142
0143
0144 void qib_get_eeprom_info(struct qib_devdata *dd)
0145 {
0146 void *buf;
0147 struct qib_flash *ifp;
0148 __be64 guid;
0149 int len, eep_stat;
0150 u8 csum, *bguid;
0151 int t = dd->unit;
0152 struct qib_devdata *dd0 = qib_lookup(0);
0153
0154 if (t && dd0->nguid > 1 && t <= dd0->nguid) {
0155 u8 oguid;
0156
0157 dd->base_guid = dd0->base_guid;
0158 bguid = (u8 *) &dd->base_guid;
0159
0160 oguid = bguid[7];
0161 bguid[7] += t;
0162 if (oguid > bguid[7]) {
0163 if (bguid[6] == 0xff) {
0164 if (bguid[5] == 0xff) {
0165 qib_dev_err(dd,
0166 "Can't set GUID from base, wraps to OUI!\n");
0167 dd->base_guid = 0;
0168 goto bail;
0169 }
0170 bguid[5]++;
0171 }
0172 bguid[6]++;
0173 }
0174 dd->nguid = 1;
0175 goto bail;
0176 }
0177
0178
0179
0180
0181
0182 len = sizeof(struct qib_flash);
0183 buf = vmalloc(len);
0184 if (!buf)
0185 goto bail;
0186
0187
0188
0189
0190
0191 eep_stat = qib_eeprom_read(dd, 0, buf, len);
0192
0193 if (eep_stat) {
0194 qib_dev_err(dd, "Failed reading GUID from eeprom\n");
0195 goto done;
0196 }
0197 ifp = (struct qib_flash *)buf;
0198
0199 csum = flash_csum(ifp, 0);
0200 if (csum != ifp->if_csum) {
0201 qib_devinfo(dd->pcidev,
0202 "Bad I2C flash checksum: 0x%x, not 0x%x\n",
0203 csum, ifp->if_csum);
0204 goto done;
0205 }
0206 if (*(__be64 *) ifp->if_guid == cpu_to_be64(0) ||
0207 *(__be64 *) ifp->if_guid == ~cpu_to_be64(0)) {
0208 qib_dev_err(dd,
0209 "Invalid GUID %llx from flash; ignoring\n",
0210 *(unsigned long long *) ifp->if_guid);
0211
0212 goto done;
0213 }
0214
0215
0216 if (*(u64 *) ifp->if_guid == 0x100007511000000ULL)
0217 qib_devinfo(dd->pcidev,
0218 "Warning, GUID %llx is default, probably not correct!\n",
0219 *(unsigned long long *) ifp->if_guid);
0220
0221 bguid = ifp->if_guid;
0222 if (!bguid[0] && !bguid[1] && !bguid[2]) {
0223
0224
0225
0226
0227
0228 bguid[1] = bguid[3];
0229 bguid[2] = bguid[4];
0230 bguid[3] = 0;
0231 bguid[4] = 0;
0232 guid = *(__be64 *) ifp->if_guid;
0233 } else
0234 guid = *(__be64 *) ifp->if_guid;
0235 dd->base_guid = guid;
0236 dd->nguid = ifp->if_numguid;
0237
0238
0239
0240
0241
0242 if ((ifp->if_fversion > 1) && ifp->if_sprefix[0] &&
0243 ((u8 *) ifp->if_sprefix)[0] != 0xFF) {
0244 char *snp = dd->serial;
0245
0246
0247
0248
0249
0250 memcpy(snp, ifp->if_sprefix, sizeof(ifp->if_sprefix));
0251 snp[sizeof(ifp->if_sprefix)] = '\0';
0252 len = strlen(snp);
0253 snp += len;
0254 len = sizeof(dd->serial) - len;
0255 if (len > sizeof(ifp->if_serial))
0256 len = sizeof(ifp->if_serial);
0257 memcpy(snp, ifp->if_serial, len);
0258 } else {
0259 memcpy(dd->serial, ifp->if_serial, sizeof(ifp->if_serial));
0260 }
0261 if (!strstr(ifp->if_comment, "Tested successfully"))
0262 qib_dev_err(dd,
0263 "Board SN %s did not pass functional test: %s\n",
0264 dd->serial, ifp->if_comment);
0265
0266 done:
0267 vfree(buf);
0268
0269 bail:;
0270 }
0271