1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Solarflare Communications Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/kmem.h> 29 #include "sfxge.h" 30 31 32 int 33 sfxge_vpd_get_keyword(sfxge_t *sp, sfxge_vpd_ioc_t *svip) 34 { 35 efx_nic_t *enp = sp->s_enp; 36 efx_vpd_value_t vpd; 37 size_t size; 38 void *buf; 39 int rc; 40 41 if ((rc = efx_vpd_size(enp, &size)) != 0) 42 goto fail1; 43 44 buf = kmem_zalloc(size, KM_SLEEP); 45 ASSERT(buf); 46 47 if ((rc = efx_vpd_read(enp, buf, size)) != 0) 48 goto fail2; 49 50 if ((rc = efx_vpd_verify(enp, buf, size)) != 0) 51 goto fail3; 52 53 vpd.evv_tag = svip->svi_tag; 54 vpd.evv_keyword = svip->svi_keyword; 55 56 if ((rc = efx_vpd_get(enp, buf, size, &vpd)) != 0) 57 goto fail4; 58 59 svip->svi_len = vpd.evv_length; 60 EFX_STATIC_ASSERT(sizeof (svip->svi_payload) == sizeof (vpd.evv_value)); 61 memcpy(svip->svi_payload, &vpd.evv_value[0], 62 sizeof (svip->svi_payload)); 63 64 kmem_free(buf, size); 65 66 return (0); 67 68 fail4: 69 DTRACE_PROBE(fail4); 70 fail3: 71 DTRACE_PROBE(fail3); 72 fail2: 73 DTRACE_PROBE(fail2); 74 kmem_free(buf, size); 75 fail1: 76 DTRACE_PROBE1(fail1, int, rc); 77 78 return (rc); 79 } 80 81 82 int 83 sfxge_vpd_set_keyword(sfxge_t *sp, sfxge_vpd_ioc_t *svip) 84 { 85 efx_nic_t *enp = sp->s_enp; 86 efx_vpd_value_t vpd; 87 size_t size; 88 void *buf; 89 int rc; 90 91 /* restriction on writable tags is in efx_vpd_hunk_set() */ 92 93 if ((rc = efx_vpd_size(enp, &size)) != 0) 94 goto fail1; 95 96 buf = kmem_zalloc(size, KM_SLEEP); 97 ASSERT(buf); 98 99 if ((rc = efx_vpd_read(enp, buf, size)) != 0) 100 goto fail2; 101 102 if ((rc = efx_vpd_verify(enp, buf, size)) != 0) { 103 if ((rc = efx_vpd_reinit(enp, buf, size)) != 0) 104 goto fail3; 105 if ((rc = efx_vpd_verify(enp, buf, size)) != 0) 106 goto fail4; 107 } 108 109 vpd.evv_tag = svip->svi_tag; 110 vpd.evv_keyword = svip->svi_keyword; 111 vpd.evv_length = svip->svi_len; 112 113 EFX_STATIC_ASSERT(sizeof (svip->svi_payload) == sizeof (vpd.evv_value)); 114 memcpy(&vpd.evv_value[0], svip->svi_payload, 115 sizeof (svip->svi_payload)); 116 117 if ((rc = efx_vpd_set(enp, buf, size, &vpd)) != 0) 118 goto fail5; 119 120 if ((rc = efx_vpd_verify(enp, buf, size)) != 0) 121 goto fail6; 122 123 /* And write the VPD back to the hardware */ 124 if ((rc = efx_vpd_write(enp, buf, size)) != 0) 125 goto fail7; 126 127 kmem_free(buf, size); 128 129 return (0); 130 131 fail7: 132 DTRACE_PROBE(fail7); 133 fail6: 134 DTRACE_PROBE(fail6); 135 fail5: 136 DTRACE_PROBE(fail5); 137 fail4: 138 DTRACE_PROBE(fail4); 139 fail3: 140 DTRACE_PROBE(fail3); 141 fail2: 142 DTRACE_PROBE(fail2); 143 kmem_free(buf, size); 144 fail1: 145 DTRACE_PROBE1(fail1, int, rc); 146 147 return (rc); 148 } 149 150 151 int 152 sfxge_vpd_ioctl(sfxge_t *sp, sfxge_vpd_ioc_t *svip) 153 { 154 int rc; 155 156 switch (svip->svi_op) { 157 case SFXGE_VPD_OP_GET_KEYWORD: 158 if ((rc = sfxge_vpd_get_keyword(sp, svip)) != 0) 159 goto fail1; 160 break; 161 case SFXGE_VPD_OP_SET_KEYWORD: 162 if ((rc = sfxge_vpd_set_keyword(sp, svip)) != 0) 163 goto fail1; 164 break; 165 default: 166 rc = EINVAL; 167 goto fail2; 168 } 169 170 return (0); 171 172 fail2: 173 DTRACE_PROBE(fail2); 174 fail1: 175 DTRACE_PROBE1(fail1, int, rc); 176 177 return (rc); 178 }