qib_eeprom.c (7358B)
1/* 2 * Copyright (c) 2012 Intel Corporation. All rights reserved. 3 * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. 4 * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 */ 34 35#include <linux/delay.h> 36#include <linux/pci.h> 37#include <linux/vmalloc.h> 38 39#include "qib.h" 40 41/* 42 * Functions specific to the serial EEPROM on cards handled by ib_qib. 43 * The actual serail interface code is in qib_twsi.c. This file is a client 44 */ 45 46/** 47 * qib_eeprom_read - receives bytes from the eeprom via I2C 48 * @dd: the qlogic_ib device 49 * @eeprom_offset: address to read from 50 * @buff: where to store result 51 * @len: number of bytes to receive 52 */ 53int qib_eeprom_read(struct qib_devdata *dd, u8 eeprom_offset, 54 void *buff, int len) 55{ 56 int ret; 57 58 ret = mutex_lock_interruptible(&dd->eep_lock); 59 if (!ret) { 60 ret = qib_twsi_reset(dd); 61 if (ret) 62 qib_dev_err(dd, "EEPROM Reset for read failed\n"); 63 else 64 ret = qib_twsi_blk_rd(dd, dd->twsi_eeprom_dev, 65 eeprom_offset, buff, len); 66 mutex_unlock(&dd->eep_lock); 67 } 68 69 return ret; 70} 71 72/* 73 * Actually update the eeprom, first doing write enable if 74 * needed, then restoring write enable state. 75 * Must be called with eep_lock held 76 */ 77static int eeprom_write_with_enable(struct qib_devdata *dd, u8 offset, 78 const void *buf, int len) 79{ 80 int ret, pwen; 81 82 pwen = dd->f_eeprom_wen(dd, 1); 83 ret = qib_twsi_reset(dd); 84 if (ret) 85 qib_dev_err(dd, "EEPROM Reset for write failed\n"); 86 else 87 ret = qib_twsi_blk_wr(dd, dd->twsi_eeprom_dev, 88 offset, buf, len); 89 dd->f_eeprom_wen(dd, pwen); 90 return ret; 91} 92 93/** 94 * qib_eeprom_write - writes data to the eeprom via I2C 95 * @dd: the qlogic_ib device 96 * @eeprom_offset: where to place data 97 * @buff: data to write 98 * @len: number of bytes to write 99 */ 100int qib_eeprom_write(struct qib_devdata *dd, u8 eeprom_offset, 101 const void *buff, int len) 102{ 103 int ret; 104 105 ret = mutex_lock_interruptible(&dd->eep_lock); 106 if (!ret) { 107 ret = eeprom_write_with_enable(dd, eeprom_offset, buff, len); 108 mutex_unlock(&dd->eep_lock); 109 } 110 111 return ret; 112} 113 114static u8 flash_csum(struct qib_flash *ifp, int adjust) 115{ 116 u8 *ip = (u8 *) ifp; 117 u8 csum = 0, len; 118 119 /* 120 * Limit length checksummed to max length of actual data. 121 * Checksum of erased eeprom will still be bad, but we avoid 122 * reading past the end of the buffer we were passed. 123 */ 124 len = ifp->if_length; 125 if (len > sizeof(struct qib_flash)) 126 len = sizeof(struct qib_flash); 127 while (len--) 128 csum += *ip++; 129 csum -= ifp->if_csum; 130 csum = ~csum; 131 if (adjust) 132 ifp->if_csum = csum; 133 134 return csum; 135} 136 137/** 138 * qib_get_eeprom_info- get the GUID et al. from the TSWI EEPROM device 139 * @dd: the qlogic_ib device 140 * 141 * We have the capability to use the nguid field, and get 142 * the guid from the first chip's flash, to use for all of them. 143 */ 144void qib_get_eeprom_info(struct qib_devdata *dd) 145{ 146 void *buf; 147 struct qib_flash *ifp; 148 __be64 guid; 149 int len, eep_stat; 150 u8 csum, *bguid; 151 int t = dd->unit; 152 struct qib_devdata *dd0 = qib_lookup(0); 153 154 if (t && dd0->nguid > 1 && t <= dd0->nguid) { 155 u8 oguid; 156 157 dd->base_guid = dd0->base_guid; 158 bguid = (u8 *) &dd->base_guid; 159 160 oguid = bguid[7]; 161 bguid[7] += t; 162 if (oguid > bguid[7]) { 163 if (bguid[6] == 0xff) { 164 if (bguid[5] == 0xff) { 165 qib_dev_err(dd, 166 "Can't set GUID from base, wraps to OUI!\n"); 167 dd->base_guid = 0; 168 goto bail; 169 } 170 bguid[5]++; 171 } 172 bguid[6]++; 173 } 174 dd->nguid = 1; 175 goto bail; 176 } 177 178 /* 179 * Read full flash, not just currently used part, since it may have 180 * been written with a newer definition. 181 * */ 182 len = sizeof(struct qib_flash); 183 buf = vmalloc(len); 184 if (!buf) 185 goto bail; 186 187 /* 188 * Use "public" eeprom read function, which does locking and 189 * figures out device. This will migrate to chip-specific. 190 */ 191 eep_stat = qib_eeprom_read(dd, 0, buf, len); 192 193 if (eep_stat) { 194 qib_dev_err(dd, "Failed reading GUID from eeprom\n"); 195 goto done; 196 } 197 ifp = (struct qib_flash *)buf; 198 199 csum = flash_csum(ifp, 0); 200 if (csum != ifp->if_csum) { 201 qib_devinfo(dd->pcidev, 202 "Bad I2C flash checksum: 0x%x, not 0x%x\n", 203 csum, ifp->if_csum); 204 goto done; 205 } 206 if (*(__be64 *) ifp->if_guid == cpu_to_be64(0) || 207 *(__be64 *) ifp->if_guid == ~cpu_to_be64(0)) { 208 qib_dev_err(dd, 209 "Invalid GUID %llx from flash; ignoring\n", 210 *(unsigned long long *) ifp->if_guid); 211 /* don't allow GUID if all 0 or all 1's */ 212 goto done; 213 } 214 215 /* complain, but allow it */ 216 if (*(u64 *) ifp->if_guid == 0x100007511000000ULL) 217 qib_devinfo(dd->pcidev, 218 "Warning, GUID %llx is default, probably not correct!\n", 219 *(unsigned long long *) ifp->if_guid); 220 221 bguid = ifp->if_guid; 222 if (!bguid[0] && !bguid[1] && !bguid[2]) { 223 /* 224 * Original incorrect GUID format in flash; fix in 225 * core copy, by shifting up 2 octets; don't need to 226 * change top octet, since both it and shifted are 0. 227 */ 228 bguid[1] = bguid[3]; 229 bguid[2] = bguid[4]; 230 bguid[3] = 0; 231 bguid[4] = 0; 232 guid = *(__be64 *) ifp->if_guid; 233 } else 234 guid = *(__be64 *) ifp->if_guid; 235 dd->base_guid = guid; 236 dd->nguid = ifp->if_numguid; 237 /* 238 * Things are slightly complicated by the desire to transparently 239 * support both the Pathscale 10-digit serial number and the QLogic 240 * 13-character version. 241 */ 242 if ((ifp->if_fversion > 1) && ifp->if_sprefix[0] && 243 ((u8 *) ifp->if_sprefix)[0] != 0xFF) { 244 char *snp = dd->serial; 245 246 /* 247 * This board has a Serial-prefix, which is stored 248 * elsewhere for backward-compatibility. 249 */ 250 memcpy(snp, ifp->if_sprefix, sizeof(ifp->if_sprefix)); 251 snp[sizeof(ifp->if_sprefix)] = '\0'; 252 len = strlen(snp); 253 snp += len; 254 len = sizeof(dd->serial) - len; 255 if (len > sizeof(ifp->if_serial)) 256 len = sizeof(ifp->if_serial); 257 memcpy(snp, ifp->if_serial, len); 258 } else { 259 memcpy(dd->serial, ifp->if_serial, sizeof(ifp->if_serial)); 260 } 261 if (!strstr(ifp->if_comment, "Tested successfully")) 262 qib_dev_err(dd, 263 "Board SN %s did not pass functional test: %s\n", 264 dd->serial, ifp->if_comment); 265 266done: 267 vfree(buf); 268 269bail:; 270} 271