Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/io/fipe/fipe_drv.c
+++ new/usr/src/uts/i86pc/io/fipe/fipe_drv.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2009, Intel Corporation.
23 23 * All rights reserved.
24 24 */
25 25
26 26 #include <sys/conf.h>
27 27 #include <sys/cmn_err.h>
28 28 #include <sys/ddi.h>
29 29 #include <sys/file.h>
30 30 #include <sys/modctl.h>
31 31 #include <sys/pci.h>
32 32 #include <sys/policy.h>
33 33 #include <sys/stat.h>
34 34 #include <sys/sunddi.h>
35 35 #include <sys/synch.h>
36 36 #include <sys/fipe.h>
37 37
38 38 /* Configurable through /etc/system. */
39 39 int fipe_allow_attach = 1;
40 40 int fipe_allow_detach = 1;
41 41
42 42 static kmutex_t fipe_drv_lock;
43 43 static dev_info_t *fipe_drv_dip;
44 44
45 45 /*
46 46 * PCI device ID for supported hardware.
47 47 * For memory controller devices in Intel 5000/7300 series chipset, PCI vendor
48 48 * id and PCI device id is read only, PCI subvendor id and PCI subsystem id is
49 49 * write-once. So we could only rely on PCI vendor id and PCI device id here.
50 50 * For all PCI functions (0,1,2,3) in device 0x10 on bus 0, they will have the
51 51 * same PCI (vendor_id, device_id, subvendor_id, subsystem_id, class_id).
52 52 * We only need to access PCI device (0, 0x10, 1), all other PCI functions will
53 53 * be filtered out by unit address.
54 54 */
55 55 static struct fipe_pci_id {
56 56 uint16_t venid;
57 57 uint16_t devid;
58 58 uint16_t subvenid;
59 59 uint16_t subsysid;
60 60 char *unitaddr;
61 61 } fipe_mc_pciids[] = {
62 62 { 0x8086, 0x25f0, 0xffff, 0xffff, "10,1" }, /* Intel 5000P/V/X/Z */
63 63 { 0x8086, 0x360c, 0xffff, 0xffff, "10,1" } /* Intel 7300 NB */
64 64 };
65 65
66 66 /*ARGSUSED*/
67 67 static int
68 68 fipe_open(dev_t *devp, int flag, int otyp, cred_t *credp)
69 69 {
70 70 if (otyp != OTYP_CHR) {
71 71 cmn_err(CE_NOTE, "!fipe: invalid otyp %d in open.", otyp);
72 72 return (EINVAL);
73 73 }
74 74
75 75 return (0);
76 76 }
77 77
78 78 /*ARGSUSED*/
79 79 static int
80 80 fipe_close(dev_t dev, int flag, int otyp, cred_t *credp)
81 81 {
82 82 return (0);
83 83 }
84 84
85 85 /*ARGSUSED*/
86 86 static int
87 87 fipe_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
88 88 int *rvalp)
89 89 {
90 90 int rc = 0;
91 91 fipe_pm_policy_t policy;
92 92
93 93 /* First check permission. */
94 94 if (secpolicy_power_mgmt(credp) != 0) {
95 95 return (EPERM);
96 96 }
97 97
98 98 switch (cmd) {
99 99 case FIPE_IOCTL_START:
100 100 if ((mode & FWRITE) == 0) {
101 101 rc = EBADF;
102 102 } else {
103 103 mutex_enter(&fipe_drv_lock);
104 104 rc = fipe_start();
105 105 mutex_exit(&fipe_drv_lock);
106 106 rc = (rc == 0) ? 0 : ENXIO;
107 107 }
108 108 break;
109 109
110 110 case FIPE_IOCTL_STOP:
111 111 if ((mode & FWRITE) == 0) {
112 112 rc = EBADF;
113 113 } else {
114 114 mutex_enter(&fipe_drv_lock);
115 115 rc = fipe_stop();
116 116 mutex_exit(&fipe_drv_lock);
117 117 rc = (rc == 0) ? 0 : ENXIO;
118 118 }
119 119 break;
120 120
121 121 case FIPE_IOCTL_GET_PMPOLICY:
122 122 if ((mode & FREAD) == 0) {
123 123 rc = EBADF;
124 124 } else {
125 125 mutex_enter(&fipe_drv_lock);
126 126 policy = fipe_get_pmpolicy();
127 127 mutex_exit(&fipe_drv_lock);
128 128 rc = ddi_copyout(&policy, (void *)arg,
129 129 sizeof (policy), mode);
130 130 rc = (rc >= 0) ? 0 : EFAULT;
131 131 }
132 132 break;
133 133
134 134 case FIPE_IOCTL_SET_PMPOLICY:
135 135 if ((mode & FWRITE) == 0) {
136 136 rc = EBADF;
137 137 } else {
138 138 mutex_enter(&fipe_drv_lock);
139 139 rc = fipe_set_pmpolicy((fipe_pm_policy_t)arg);
140 140 mutex_exit(&fipe_drv_lock);
141 141 rc = (rc == 0) ? 0 : ENXIO;
142 142 }
143 143 break;
144 144
145 145 default:
146 146 cmn_err(CE_NOTE, "!fipe: unknown ioctl command %d.", cmd);
147 147 rc = ENOTSUP;
148 148 break;
149 149 }
150 150
151 151 return (rc);
152 152 }
153 153
154 154 /*ARGSUSED*/
155 155 static int
156 156 fipe_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
157 157 {
158 158 switch (infocmd) {
159 159 case DDI_INFO_DEVT2DEVINFO:
160 160 if (fipe_drv_dip != NULL) {
161 161 *result = fipe_drv_dip;
162 162 return (DDI_SUCCESS);
163 163 } else {
164 164 *result = NULL;
165 165 return (DDI_FAILURE);
166 166 }
167 167
168 168 case DDI_INFO_DEVT2INSTANCE:
169 169 if (fipe_drv_dip != NULL) {
170 170 *result = (void *)(uintptr_t)
171 171 ddi_get_instance(fipe_drv_dip);
172 172 return (DDI_SUCCESS);
173 173 } else {
174 174 *result = NULL;
175 175 return (DDI_FAILURE);
176 176 }
177 177
178 178 default:
179 179 *result = NULL;
180 180 return (DDI_FAILURE);
181 181 }
182 182 }
183 183
184 184 /* Validate whether it's supported hardware. */
185 185 static int
186 186 fipe_validate_dip(dev_info_t *dip)
187 187 {
188 188 int i, rc = -1;
189 189 char *unitaddr;
190 190 struct fipe_pci_id *ip;
191 191 ddi_acc_handle_t handle;
192 192 uint16_t venid, devid, subvenid, subsysid;
193 193
194 194 /* Get device unit address, it's "devid,funcid" in hexadecimal. */
195 195 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
196 196 "unit-address", &unitaddr) != DDI_PROP_SUCCESS) {
197 197 cmn_err(CE_CONT, "?fipe: failed to get deivce unit address.");
198 198 return (-1);
199 199 }
200 200 if (pci_config_setup(dip, &handle) != DDI_SUCCESS) {
201 201 cmn_err(CE_CONT, "?fipe: failed to setup pcicfg handler.");
202 202 ddi_prop_free(unitaddr);
203 203 return (-1);
204 204 }
205 205 venid = pci_config_get16(handle, PCI_CONF_VENID);
206 206 devid = pci_config_get16(handle, PCI_CONF_DEVID);
207 207 subvenid = pci_config_get16(handle, PCI_CONF_SUBVENID);
208 208 subsysid = pci_config_get16(handle, PCI_CONF_SUBSYSID);
209 209
210 210 /* Validate device. */
211 211 for (rc = -1, i = 0, ip = &fipe_mc_pciids[0];
212 212 i < sizeof (fipe_mc_pciids) / sizeof (fipe_mc_pciids[0]);
213 213 i++, ip++) {
214 214 if ((ip->venid == 0xffffu || ip->venid == venid) &&
215 215 (ip->devid == 0xffffu || ip->devid == devid) &&
216 216 (ip->subvenid == 0xffffu || ip->subvenid == subvenid) &&
217 217 (ip->subsysid == 0xffffu || ip->subsysid == subsysid) &&
218 218 (ip->unitaddr == NULL ||
219 219 strcmp(ip->unitaddr, unitaddr) == 0)) {
220 220 rc = 0;
221 221 break;
222 222 }
223 223 }
224 224
225 225 pci_config_teardown(&handle);
226 226 ddi_prop_free(unitaddr);
227 227
228 228 return (rc);
229 229 }
230 230
231 231 static int
232 232 fipe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
233 233 {
234 234 char *ptr;
235 235 int ignore = 0, rc = DDI_FAILURE;
236 236
237 237 mutex_enter(&fipe_drv_lock);
238 238 switch (cmd) {
239 239 case DDI_ATTACH:
240 240 /* Check whether it has been disabled by user. */
241 241 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
242 242 "disable_fipe_pm", &ptr) == DDI_SUCCESS) {
243 243 if (strcasecmp(ptr, "true") == 0 ||
244 244 strcasecmp(ptr, "yes") == 0) {
245 245 fipe_allow_attach = 0;
246 246 }
247 247 ddi_prop_free(ptr);
248 248 }
249 249 if (fipe_allow_attach == 0) {
250 250 cmn_err(CE_WARN,
251 251 "fipe: driver has been disabled by user.");
252 252 ignore = 1;
253 253 break;
254 254 }
255 255
256 256 /* Filter out unwanted PCI functions. */
257 257 if ((ignore = fipe_validate_dip(dip)) != 0) {
258 258 break;
259 259 /* There should be only one MC device in system. */
260 260 } else if (fipe_drv_dip != NULL) {
261 261 cmn_err(CE_NOTE,
262 262 "!fipe: more than one hardware instances found.");
263 263 break;
264 264 }
265 265 fipe_drv_dip = dip;
266 266
267 267 /* Initialize and start power management subsystem. */
268 268 if (fipe_init(fipe_drv_dip) != 0) {
269 269 fipe_drv_dip = NULL;
270 270 break;
271 271 } else if (fipe_start() != 0) {
272 272 (void) fipe_fini();
273 273 fipe_drv_dip = NULL;
274 274 break;
275 275 }
276 276
277 277 /* Ignore error from creating minor node. */
278 278 if (ddi_create_minor_node(dip, "fipe", S_IFCHR, 0,
279 279 "ddi_mem_pm", 0) != DDI_SUCCESS) {
280 280 cmn_err(CE_CONT,
281 281 "?fipe: failed to create device minor node.\n");
282 282 }
283 283
284 284 rc = DDI_SUCCESS;
285 285 break;
286 286
287 287 case DDI_RESUME:
288 288 if (fipe_resume() == 0) {
289 289 rc = DDI_SUCCESS;
290 290 }
291 291 break;
292 292
293 293 default:
294 294 break;
295 295 }
296 296 mutex_exit(&fipe_drv_lock);
297 297
298 298 if (ignore == 0 && rc != DDI_SUCCESS) {
299 299 cmn_err(CE_NOTE, "!fipe: failed to attach or resume device.");
300 300 }
301 301
302 302 return (rc);
303 303 }
304 304
305 305 /*ARGSUSED*/
306 306 static int
307 307 fipe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
308 308 {
309 309 int rc = DDI_FAILURE;
310 310
311 311 mutex_enter(&fipe_drv_lock);
312 312 switch (cmd) {
313 313 case DDI_DETACH:
314 314 if (fipe_allow_detach == 0 || dip != fipe_drv_dip) {
315 315 break;
316 316 }
317 317 if (fipe_stop() != 0) {
318 318 break;
319 319 } else if (fipe_fini() != 0) {
320 320 (void) fipe_start();
321 321 break;
322 322 }
323 323 ddi_remove_minor_node(dip, NULL);
324 324 fipe_drv_dip = NULL;
325 325 rc = DDI_SUCCESS;
326 326 break;
327 327
328 328 case DDI_SUSPEND:
329 329 if (fipe_suspend() == 0) {
330 330 rc = DDI_SUCCESS;
331 331 }
332 332 break;
333 333
334 334 default:
335 335 break;
336 336 }
337 337 mutex_exit(&fipe_drv_lock);
338 338
339 339 if (rc != DDI_SUCCESS) {
340 340 cmn_err(CE_NOTE, "!fipe: failed to detach or suspend device.");
341 341 }
342 342
343 343 return (rc);
344 344 }
345 345
346 346 static int
347 347 fipe_quiesce(dev_info_t *dip)
348 348 {
349 349 if (dip != fipe_drv_dip) {
350 350 return (DDI_SUCCESS);
351 351 }
352 352 /* Quiesce hardware by stopping power management subsystem. */
353 353 if (fipe_suspend() != 0) {
354 354 cmn_err(CE_NOTE, "!fipe: failed to quiesce device.");
355 355 return (DDI_FAILURE);
356 356 }
357 357
358 358 return (DDI_SUCCESS);
359 359 }
360 360
361 361 static struct cb_ops fipe_cb_ops = {
362 362 fipe_open,
363 363 fipe_close,
364 364 nodev, /* not a block driver */
365 365 nodev, /* no print routine */
366 366 nodev, /* no dump routine */
367 367 nodev, /* no read routine */
368 368 nodev, /* no write routine */
369 369 fipe_ioctl,
370 370 nodev, /* no devmap routine */
371 371 nodev, /* no mmap routine */
372 372 nodev, /* no segmap routine */
373 373 nochpoll, /* no chpoll routine */
374 374 ddi_prop_op,
375 375 0, /* not a STREAMS driver */
376 376 D_NEW | D_MP, /* safe for multi-thread/multi-processor */
377 377 };
378 378
379 379 static struct dev_ops fipe_ops = {
380 380 DEVO_REV, /* devo_rev */
381 381 0, /* devo_refcnt */
382 382 fipe_getinfo, /* devo_getinfo */
383 383 nulldev, /* devo_identify */
384 384 nulldev, /* devo_probe */
385 385 fipe_attach, /* devo_attach */
386 386 fipe_detach, /* devo_detach */
387 387 nodev, /* devo_reset */
388 388 &fipe_cb_ops, /* devo_cb_ops */
389 389 NULL, /* devo_bus_ops */
390 390 NULL, /* devo_power */
391 391 &fipe_quiesce, /* devo_quiesce */
↓ open down ↓ |
391 lines elided |
↑ open up ↑ |
392 392 };
393 393
394 394 static struct modldrv modldrv = {
395 395 &mod_driverops,
396 396 "Intel 5000/7300 memory controller driver",
397 397 &fipe_ops
398 398 };
399 399
400 400 static struct modlinkage modlinkage = {
401 401 MODREV_1,
402 - (void *)&modldrv,
403 - NULL
402 + { (void *)&modldrv, NULL }
404 403 };
405 404
406 405 int
407 406 _init(void)
408 407 {
409 408 fipe_drv_dip = NULL;
410 409 mutex_init(&fipe_drv_lock, NULL, MUTEX_DRIVER, NULL);
411 410
412 411 return (mod_install(&modlinkage));
413 412 }
414 413
415 414 int
416 415 _info(struct modinfo *modinfop)
417 416 {
418 417 return (mod_info(&modlinkage, modinfop));
419 418 }
420 419
421 420 int
422 421 _fini(void)
423 422 {
424 423 int err;
425 424
426 425 if ((err = mod_remove(&modlinkage)) == 0) {
427 426 mutex_destroy(&fipe_drv_lock);
428 427 fipe_drv_dip = NULL;
429 428 }
430 429
431 430 return (err);
432 431 }
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX