1 /* 2 * Copyright (c) 2009-2015 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 #include <sys/types.h> 32 #include <sys/kmem.h> 33 #include "sfxge.h" 34 35 36 static int 37 sfxge_vpd_get_keyword(sfxge_t *sp, sfxge_vpd_ioc_t *svip) 38 { 39 efx_nic_t *enp = sp->s_enp; 40 efx_vpd_value_t vpd; 41 size_t size; 42 void *buf; 43 int rc; 44 45 if ((rc = efx_vpd_size(enp, &size)) != 0) 46 goto fail1; 47 48 buf = kmem_zalloc(size, KM_SLEEP); 49 ASSERT(buf); 50 51 if ((rc = efx_vpd_read(enp, buf, size)) != 0) 52 goto fail2; 53 54 if ((rc = efx_vpd_verify(enp, buf, size)) != 0) 55 goto fail3; 56 57 vpd.evv_tag = svip->svi_tag; 58 vpd.evv_keyword = svip->svi_keyword; 59 60 if ((rc = efx_vpd_get(enp, buf, size, &vpd)) != 0) 61 goto fail4; 62 63 svip->svi_len = vpd.evv_length; 64 EFX_STATIC_ASSERT(sizeof (svip->svi_payload) == sizeof (vpd.evv_value)); 65 bcopy(&vpd.evv_value[0], svip->svi_payload, sizeof (svip->svi_payload)); 66 67 kmem_free(buf, size); 68 69 return (0); 70 71 fail4: 72 DTRACE_PROBE(fail4); 73 fail3: 74 DTRACE_PROBE(fail3); 75 fail2: 76 DTRACE_PROBE(fail2); 77 kmem_free(buf, size); 78 fail1: 79 DTRACE_PROBE1(fail1, int, rc); 80 81 return (rc); 82 } 83 84 85 static int 86 sfxge_vpd_set_keyword(sfxge_t *sp, sfxge_vpd_ioc_t *svip) 87 { 88 efx_nic_t *enp = sp->s_enp; 89 efx_vpd_value_t vpd; 90 size_t size; 91 void *buf; 92 int rc; 93 94 /* restriction on writable tags is in efx_vpd_hunk_set() */ 95 96 if ((rc = efx_vpd_size(enp, &size)) != 0) 97 goto fail1; 98 99 buf = kmem_zalloc(size, KM_SLEEP); 100 ASSERT(buf); 101 102 if ((rc = efx_vpd_read(enp, buf, size)) != 0) 103 goto fail2; 104 105 if ((rc = efx_vpd_verify(enp, buf, size)) != 0) { 106 if ((rc = efx_vpd_reinit(enp, buf, size)) != 0) 107 goto fail3; 108 if ((rc = efx_vpd_verify(enp, buf, size)) != 0) 109 goto fail4; 110 } 111 112 vpd.evv_tag = svip->svi_tag; 113 vpd.evv_keyword = svip->svi_keyword; 114 vpd.evv_length = svip->svi_len; 115 116 EFX_STATIC_ASSERT(sizeof (svip->svi_payload) == sizeof (vpd.evv_value)); 117 bcopy(svip->svi_payload, &vpd.evv_value[0], sizeof (svip->svi_payload)); 118 119 if ((rc = efx_vpd_set(enp, buf, size, &vpd)) != 0) 120 goto fail5; 121 122 if ((rc = efx_vpd_verify(enp, buf, size)) != 0) 123 goto fail6; 124 125 /* And write the VPD back to the hardware */ 126 if ((rc = efx_vpd_write(enp, buf, size)) != 0) 127 goto fail7; 128 129 kmem_free(buf, size); 130 131 return (0); 132 133 fail7: 134 DTRACE_PROBE(fail7); 135 fail6: 136 DTRACE_PROBE(fail6); 137 fail5: 138 DTRACE_PROBE(fail5); 139 fail4: 140 DTRACE_PROBE(fail4); 141 fail3: 142 DTRACE_PROBE(fail3); 143 fail2: 144 DTRACE_PROBE(fail2); 145 kmem_free(buf, size); 146 fail1: 147 DTRACE_PROBE1(fail1, int, rc); 148 149 return (rc); 150 } 151 152 153 int 154 sfxge_vpd_ioctl(sfxge_t *sp, sfxge_vpd_ioc_t *svip) 155 { 156 int rc; 157 158 switch (svip->svi_op) { 159 case SFXGE_VPD_OP_GET_KEYWORD: 160 if ((rc = sfxge_vpd_get_keyword(sp, svip)) != 0) 161 goto fail1; 162 break; 163 case SFXGE_VPD_OP_SET_KEYWORD: 164 if ((rc = sfxge_vpd_set_keyword(sp, svip)) != 0) 165 goto fail1; 166 break; 167 default: 168 rc = EINVAL; 169 goto fail2; 170 } 171 172 return (0); 173 174 fail2: 175 DTRACE_PROBE(fail2); 176 fail1: 177 DTRACE_PROBE1(fail1, int, rc); 178 179 return (rc); 180 }