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 }