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 }