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 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * SCSI FMA implementation
27 */
28
29 #include <sys/scsi/scsi_types.h>
30 #include <sys/sunmdi.h>
31 #include <sys/va_list.h>
32
33 #include <sys/ddi_impldefs.h>
34
35 /* consolidation private interface to generate dev scheme ereport */
36 extern void fm_dev_ereport_postv(dev_info_t *dip, dev_info_t *eqdip,
37 const char *devpath, const char *minor_name, const char *devid,
38 const char *tpl0, const char *error_class, uint64_t ena, int sflag,
39 nvlist_t *, va_list ap);
40 extern char *mdi_pi_pathname_by_instance(int);
41
42 #define FM_SCSI_CLASS "scsi"
82 {
83 dev_info_t *dip = sd->sd_dev;
84
85 if (sd->sd_fm_capable != DDI_FM_NOT_CAPABLE)
86 ddi_fm_fini(dip);
87 }
88
89 /*
90 *
91 * scsi_fm_ereport_post - Post an ereport
92 */
93 void
94 scsi_fm_ereport_post(struct scsi_device *sd, int path_instance,
95 char *devpath, const char *error_class, uint64_t ena,
96 char *devid, char *tpl0, int sflag, nvlist_t *pl, ...)
97 {
98 char class[ERPT_CLASS_SZ];
99 dev_info_t *dip = sd->sd_dev;
100 dev_info_t *eqdip = dip;
101 char *minor_name;
102 va_list ap;
103
104 /*
105 * If the scsi_device eqdip is not yet ereport capable, send the
106 * report based on parent capabilities. This is needed for
107 * telemetry during enumeration.
108 */
109 if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(eqdip)))
110 eqdip = ddi_get_parent(eqdip);
111
112 /* Add "scsi." as a prefix to the class */
113 (void) snprintf(class, ERPT_CLASS_SZ, "%s.%s",
114 FM_SCSI_CLASS, error_class);
115
116 /*
117 * Get the path:
118 *
119 * If path_instance is non-zero then the packet was
120 * sent to scsi_vhci. We return the pathinfo path_string associated
121 * with the path_instance path - which refers to the actual hardware.
122 *
123 * If path_instance is zero then use the devpath provided by the
124 * caller; if it was NULL then this will cause fm_dev_ereport_post
125 * to use the devinfo path of the first devi we pass to it, ie
126 * sd->sd_dev.
127 */
128 if (path_instance)
129 devpath = mdi_pi_pathname_by_instance(path_instance);
130
131 /*
132 * Set the minor_name to NULL. The block location of a media error
133 * is described by the 'lba' property. We use the 'lba' instead of
134 * the partition (minor_name) because the defect stays in the same
135 * place even when a repartition operation may result in the defect
136 * showing up in a different partition (minor_name). To support
137 * retire at the block/partition level, the user level retire agent
138 * should map the 'lba' to the current effected partition.
139 */
140 minor_name = NULL;
141
142 /*
143 * NOTE: If there is a 'linked' ena to be had, it should likely come
144 * from the buf structure via the scsi_pkt pkt->pkt_bp.
145 */
146
147 /* Post the ereport */
148 va_start(ap, pl);
149 fm_dev_ereport_postv(dip, eqdip, devpath, minor_name, devid, tpl0,
150 class, ena, sflag, pl, ap);
151 va_end(ap);
152 }
|
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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc.
25 */
26
27 /*
28 * SCSI FMA implementation
29 */
30
31 #include <sys/scsi/scsi_types.h>
32 #include <sys/sunmdi.h>
33 #include <sys/va_list.h>
34
35 #include <sys/ddi_impldefs.h>
36
37 /* consolidation private interface to generate dev scheme ereport */
38 extern void fm_dev_ereport_postv(dev_info_t *dip, dev_info_t *eqdip,
39 const char *devpath, const char *minor_name, const char *devid,
40 const char *tpl0, const char *error_class, uint64_t ena, int sflag,
41 nvlist_t *, va_list ap);
42 extern char *mdi_pi_pathname_by_instance(int);
43
44 #define FM_SCSI_CLASS "scsi"
84 {
85 dev_info_t *dip = sd->sd_dev;
86
87 if (sd->sd_fm_capable != DDI_FM_NOT_CAPABLE)
88 ddi_fm_fini(dip);
89 }
90
91 /*
92 *
93 * scsi_fm_ereport_post - Post an ereport
94 */
95 void
96 scsi_fm_ereport_post(struct scsi_device *sd, int path_instance,
97 char *devpath, const char *error_class, uint64_t ena,
98 char *devid, char *tpl0, int sflag, nvlist_t *pl, ...)
99 {
100 char class[ERPT_CLASS_SZ];
101 dev_info_t *dip = sd->sd_dev;
102 dev_info_t *eqdip = dip;
103 char *minor_name;
104 nvlist_t *nvl;
105 char *prop;
106 va_list ap;
107
108 /*
109 * If the scsi_device eqdip is not yet ereport capable, send the
110 * report based on parent capabilities. This is needed for
111 * telemetry during enumeration.
112 */
113 if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(eqdip)))
114 eqdip = ddi_get_parent(eqdip);
115
116 /* Add "scsi." as a prefix to the class */
117 (void) snprintf(class, ERPT_CLASS_SZ, "%s.%s",
118 FM_SCSI_CLASS, error_class);
119
120 /*
121 * Get the path:
122 *
123 * If path_instance is non-zero then the packet was
124 * sent to scsi_vhci. We return the pathinfo path_string associated
125 * with the path_instance path - which refers to the actual hardware.
126 *
127 * If path_instance is zero then use the devpath provided by the
128 * caller; if it was NULL then this will cause fm_dev_ereport_post
129 * to use the devinfo path of the first devi we pass to it, ie
130 * sd->sd_dev.
131 */
132 if (path_instance)
133 devpath = mdi_pi_pathname_by_instance(path_instance);
134
135 /*
136 * Set the minor_name to NULL. The block location of a media error
137 * is described by the 'lba' property. We use the 'lba' instead of
138 * the partition (minor_name) because the defect stays in the same
139 * place even when a repartition operation may result in the defect
140 * showing up in a different partition (minor_name). To support
141 * retire at the block/partition level, the user level retire agent
142 * should map the 'lba' to the current effected partition.
143 */
144 minor_name = NULL;
145
146 /* Create nvlist containing inquiry properties (if available) */
147 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, (sflag & DDI_NOSLEEP) ?
148 KM_NOSLEEP : KM_SLEEP) != 0)
149 return;
150 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
151 INQUIRY_VENDOR_ID, &prop) == DDI_PROP_SUCCESS) {
152 (void) nvlist_add_string(nvl, "vendor", prop);
153 ddi_prop_free(prop);
154 }
155 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
156 INQUIRY_PRODUCT_ID, &prop) == DDI_PROP_SUCCESS) {
157 (void) nvlist_add_string(nvl, "product", prop);
158 ddi_prop_free(prop);
159 }
160 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
161 INQUIRY_REVISION_ID, &prop) == DDI_PROP_SUCCESS) {
162 (void) nvlist_add_string(nvl, "revision", prop);
163 ddi_prop_free(prop);
164 }
165 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
166 INQUIRY_SERIAL_NO, &prop) == DDI_PROP_SUCCESS) {
167 (void) nvlist_add_string(nvl, "serial", prop);
168 ddi_prop_free(prop);
169 }
170 /* Merge the provided payload if any */
171 if (pl != NULL)
172 (void) nvlist_merge(nvl, pl, 0);
173
174 /*
175 * NOTE: If there is a 'linked' ena to be had, it should likely come
176 * from the buf structure via the scsi_pkt pkt->pkt_bp.
177 */
178
179 /* Post the ereport */
180 va_start(ap, pl);
181 fm_dev_ereport_postv(dip, eqdip, devpath, minor_name, devid, tpl0,
182 class, ena, sflag, nvl, ap);
183 va_end(ap);
184
185 nvlist_free(nvl);
186 }
|