Print this page
NEX-8020 illumos nvme changes
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-6131 support EUI64 in blkdev
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-5236 harmless off-by-one in blkdev
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-4427 blkdev should provide the device_error kstat for iostat -E
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
NEX-4424 kstat module needs cleanup
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
NEX-4420 format(1M) should be able to use device inquiry properties
Reviewed by: Dan McDonald <danmcd@omniti.com>
NEX-4419 blkdev and blkdev drivers should provide inquiry properties
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
port of illumos-3878
3878 blkdev needs to support DKIOCGMEDIAINFOEXT
Reviewed by: Saso Kiselkov <skiselkov.ml@gmail.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Garrett D'Amore <garrett@damore.org>
port of illumos-2911
2911 blkdev-related panic on DEBUG kernels
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Garrett D'Amore <garrett@damore.org>
Adding AoE support to nza-kernel
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/blkdev/blkdev.c
+++ new/usr/src/uts/common/io/blkdev/blkdev.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, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
24 24 * Copyright 2012 Alexey Zaytsev <alexey.zaytsev@gmail.com> All rights reserved.
25 25 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
26 26 * Copyright 2017 The MathWorks, Inc. All rights reserved.
27 27 */
28 28
29 29 #include <sys/types.h>
30 30 #include <sys/ksynch.h>
31 31 #include <sys/kmem.h>
32 32 #include <sys/file.h>
33 33 #include <sys/errno.h>
34 34 #include <sys/open.h>
35 35 #include <sys/buf.h>
36 36 #include <sys/uio.h>
37 37 #include <sys/aio_req.h>
38 38 #include <sys/cred.h>
39 39 #include <sys/modctl.h>
40 40 #include <sys/cmlb.h>
41 41 #include <sys/conf.h>
42 42 #include <sys/devops.h>
|
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
43 43 #include <sys/list.h>
44 44 #include <sys/sysmacros.h>
45 45 #include <sys/dkio.h>
46 46 #include <sys/vtoc.h>
47 47 #include <sys/scsi/scsi.h> /* for DTYPE_DIRECT */
48 48 #include <sys/kstat.h>
49 49 #include <sys/fs/dv_node.h>
50 50 #include <sys/ddi.h>
51 51 #include <sys/sunddi.h>
52 52 #include <sys/note.h>
53 +#include <sys/mhd.h>
53 54 #include <sys/blkdev.h>
54 55 #include <sys/scsi/impl/inquiry.h>
55 56
56 57 #define BD_MAXPART 64
57 58 #define BDINST(dev) (getminor(dev) / BD_MAXPART)
58 59 #define BDPART(dev) (getminor(dev) % BD_MAXPART)
59 60
60 61 typedef struct bd bd_t;
61 62 typedef struct bd_xfer_impl bd_xfer_impl_t;
62 63
63 64 struct bd {
64 65 void *d_private;
65 66 dev_info_t *d_dip;
66 67 kmutex_t d_ocmutex;
67 68 kmutex_t d_iomutex;
68 69 kmutex_t *d_errmutex;
69 70 kmutex_t d_statemutex;
70 71 kcondvar_t d_statecv;
71 72 enum dkio_state d_state;
72 73 cmlb_handle_t d_cmlbh;
73 74 unsigned d_open_lyr[BD_MAXPART]; /* open count */
74 75 uint64_t d_open_excl; /* bit mask indexed by partition */
75 76 uint64_t d_open_reg[OTYPCNT]; /* bit mask */
76 77
77 78 uint32_t d_qsize;
78 79 uint32_t d_qactive;
79 80 uint32_t d_maxxfer;
80 81 uint32_t d_blkshift;
81 82 uint32_t d_pblkshift;
82 83 uint64_t d_numblks;
83 84 ddi_devid_t d_devid;
84 85
85 86 kmem_cache_t *d_cache;
86 87 list_t d_runq;
87 88 list_t d_waitq;
88 89 kstat_t *d_ksp;
89 90 kstat_io_t *d_kiop;
90 91 kstat_t *d_errstats;
91 92 struct bd_errstats *d_kerr;
92 93
93 94 boolean_t d_rdonly;
94 95 boolean_t d_ssd;
95 96 boolean_t d_removable;
96 97 boolean_t d_hotpluggable;
97 98 boolean_t d_use_dma;
98 99
99 100 ddi_dma_attr_t d_dma;
100 101 bd_ops_t d_ops;
101 102 bd_handle_t d_handle;
102 103 };
103 104
104 105 struct bd_handle {
105 106 bd_ops_t h_ops;
106 107 ddi_dma_attr_t *h_dma;
107 108 dev_info_t *h_parent;
108 109 dev_info_t *h_child;
109 110 void *h_private;
110 111 bd_t *h_bd;
111 112 char *h_name;
112 113 char h_addr[30]; /* enough for w%0.16x,%X */
113 114 };
114 115
115 116 struct bd_xfer_impl {
116 117 bd_xfer_t i_public;
117 118 list_node_t i_linkage;
118 119 bd_t *i_bd;
119 120 buf_t *i_bp;
120 121 uint_t i_num_win;
121 122 uint_t i_cur_win;
122 123 off_t i_offset;
123 124 int (*i_func)(void *, bd_xfer_t *);
124 125 uint32_t i_blkshift;
125 126 size_t i_len;
126 127 size_t i_resid;
127 128 };
128 129
129 130 #define i_dmah i_public.x_dmah
130 131 #define i_dmac i_public.x_dmac
131 132 #define i_ndmac i_public.x_ndmac
132 133 #define i_kaddr i_public.x_kaddr
133 134 #define i_nblks i_public.x_nblks
134 135 #define i_blkno i_public.x_blkno
135 136 #define i_flags i_public.x_flags
136 137
137 138
138 139 /*
139 140 * Private prototypes.
140 141 */
141 142
142 143 static void bd_prop_update_inqstring(dev_info_t *, char *, char *, size_t);
143 144 static void bd_create_inquiry_props(dev_info_t *, bd_drive_t *);
144 145 static void bd_create_errstats(bd_t *, int, bd_drive_t *);
145 146 static void bd_errstats_setstr(kstat_named_t *, char *, size_t, char *);
146 147 static void bd_init_errstats(bd_t *, bd_drive_t *);
147 148
148 149 static int bd_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
149 150 static int bd_attach(dev_info_t *, ddi_attach_cmd_t);
150 151 static int bd_detach(dev_info_t *, ddi_detach_cmd_t);
151 152
152 153 static int bd_open(dev_t *, int, int, cred_t *);
153 154 static int bd_close(dev_t, int, int, cred_t *);
154 155 static int bd_strategy(struct buf *);
155 156 static int bd_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
156 157 static int bd_dump(dev_t, caddr_t, daddr_t, int);
157 158 static int bd_read(dev_t, struct uio *, cred_t *);
158 159 static int bd_write(dev_t, struct uio *, cred_t *);
159 160 static int bd_aread(dev_t, struct aio_req *, cred_t *);
160 161 static int bd_awrite(dev_t, struct aio_req *, cred_t *);
161 162 static int bd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
162 163 caddr_t, int *);
163 164
164 165 static int bd_tg_rdwr(dev_info_t *, uchar_t, void *, diskaddr_t, size_t,
|
↓ open down ↓ |
102 lines elided |
↑ open up ↑ |
165 166 void *);
166 167 static int bd_tg_getinfo(dev_info_t *, int, void *, void *);
167 168 static int bd_xfer_ctor(void *, void *, int);
168 169 static void bd_xfer_dtor(void *, void *);
169 170 static void bd_sched(bd_t *);
170 171 static void bd_submit(bd_t *, bd_xfer_impl_t *);
171 172 static void bd_runq_exit(bd_xfer_impl_t *, int);
172 173 static void bd_update_state(bd_t *);
173 174 static int bd_check_state(bd_t *, enum dkio_state *);
174 175 static int bd_flush_write_cache(bd_t *, struct dk_callback *);
176 +static int bd_reserve(bd_t *bd, int);
175 177 static int bd_check_uio(dev_t, struct uio *);
176 178
177 179 struct cmlb_tg_ops bd_tg_ops = {
178 180 TG_DK_OPS_VERSION_1,
179 181 bd_tg_rdwr,
180 182 bd_tg_getinfo,
181 183 };
182 184
183 185 static struct cb_ops bd_cb_ops = {
184 186 bd_open, /* open */
185 187 bd_close, /* close */
186 188 bd_strategy, /* strategy */
187 189 nodev, /* print */
188 190 bd_dump, /* dump */
189 191 bd_read, /* read */
190 192 bd_write, /* write */
191 193 bd_ioctl, /* ioctl */
192 194 nodev, /* devmap */
193 195 nodev, /* mmap */
194 196 nodev, /* segmap */
195 197 nochpoll, /* poll */
196 198 bd_prop_op, /* cb_prop_op */
197 199 0, /* streamtab */
198 200 D_64BIT | D_MP, /* Driver comaptibility flag */
199 201 CB_REV, /* cb_rev */
200 202 bd_aread, /* async read */
201 203 bd_awrite /* async write */
202 204 };
203 205
204 206 struct dev_ops bd_dev_ops = {
205 207 DEVO_REV, /* devo_rev, */
206 208 0, /* refcnt */
207 209 bd_getinfo, /* getinfo */
208 210 nulldev, /* identify */
209 211 nulldev, /* probe */
210 212 bd_attach, /* attach */
211 213 bd_detach, /* detach */
212 214 nodev, /* reset */
213 215 &bd_cb_ops, /* driver operations */
214 216 NULL, /* bus operations */
215 217 NULL, /* power */
216 218 ddi_quiesce_not_needed, /* quiesce */
217 219 };
218 220
219 221 static struct modldrv modldrv = {
220 222 &mod_driverops,
221 223 "Generic Block Device",
222 224 &bd_dev_ops,
223 225 };
224 226
225 227 static struct modlinkage modlinkage = {
226 228 MODREV_1, { &modldrv, NULL }
227 229 };
228 230
229 231 static void *bd_state;
230 232 static krwlock_t bd_lock;
231 233
232 234 int
233 235 _init(void)
234 236 {
235 237 int rv;
236 238
237 239 rv = ddi_soft_state_init(&bd_state, sizeof (struct bd), 2);
238 240 if (rv != DDI_SUCCESS) {
239 241 return (rv);
240 242 }
241 243 rw_init(&bd_lock, NULL, RW_DRIVER, NULL);
242 244 rv = mod_install(&modlinkage);
243 245 if (rv != DDI_SUCCESS) {
244 246 rw_destroy(&bd_lock);
245 247 ddi_soft_state_fini(&bd_state);
246 248 }
247 249 return (rv);
248 250 }
249 251
250 252 int
251 253 _fini(void)
252 254 {
253 255 int rv;
254 256
255 257 rv = mod_remove(&modlinkage);
256 258 if (rv == DDI_SUCCESS) {
257 259 rw_destroy(&bd_lock);
258 260 ddi_soft_state_fini(&bd_state);
259 261 }
260 262 return (rv);
261 263 }
262 264
263 265 int
264 266 _info(struct modinfo *modinfop)
265 267 {
266 268 return (mod_info(&modlinkage, modinfop));
267 269 }
268 270
269 271 static int
270 272 bd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
271 273 {
272 274 bd_t *bd;
273 275 minor_t inst;
274 276
275 277 _NOTE(ARGUNUSED(dip));
276 278
277 279 inst = BDINST((dev_t)arg);
278 280
279 281 switch (cmd) {
280 282 case DDI_INFO_DEVT2DEVINFO:
281 283 bd = ddi_get_soft_state(bd_state, inst);
282 284 if (bd == NULL) {
283 285 return (DDI_FAILURE);
284 286 }
285 287 *resultp = (void *)bd->d_dip;
286 288 break;
287 289
288 290 case DDI_INFO_DEVT2INSTANCE:
289 291 *resultp = (void *)(intptr_t)inst;
290 292 break;
291 293
292 294 default:
293 295 return (DDI_FAILURE);
294 296 }
295 297 return (DDI_SUCCESS);
296 298 }
297 299
298 300 static void
299 301 bd_prop_update_inqstring(dev_info_t *dip, char *name, char *data, size_t len)
300 302 {
301 303 int ilen;
302 304 char *data_string;
303 305
304 306 ilen = scsi_ascii_inquiry_len(data, len);
305 307 ASSERT3U(ilen, <=, len);
306 308 if (ilen <= 0)
307 309 return;
308 310 /* ensure null termination */
309 311 data_string = kmem_zalloc(ilen + 1, KM_SLEEP);
310 312 bcopy(data, data_string, ilen);
311 313 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, name, data_string);
312 314 kmem_free(data_string, ilen + 1);
313 315 }
314 316
315 317 static void
316 318 bd_create_inquiry_props(dev_info_t *dip, bd_drive_t *drive)
317 319 {
318 320 if (drive->d_vendor_len > 0)
319 321 bd_prop_update_inqstring(dip, INQUIRY_VENDOR_ID,
320 322 drive->d_vendor, drive->d_vendor_len);
321 323
322 324 if (drive->d_product_len > 0)
323 325 bd_prop_update_inqstring(dip, INQUIRY_PRODUCT_ID,
324 326 drive->d_product, drive->d_product_len);
325 327
326 328 if (drive->d_serial_len > 0)
327 329 bd_prop_update_inqstring(dip, INQUIRY_SERIAL_NO,
328 330 drive->d_serial, drive->d_serial_len);
329 331
330 332 if (drive->d_revision_len > 0)
331 333 bd_prop_update_inqstring(dip, INQUIRY_REVISION_ID,
332 334 drive->d_revision, drive->d_revision_len);
333 335 }
334 336
335 337 static void
336 338 bd_create_errstats(bd_t *bd, int inst, bd_drive_t *drive)
337 339 {
338 340 char ks_module[KSTAT_STRLEN];
339 341 char ks_name[KSTAT_STRLEN];
340 342 int ndata = sizeof (struct bd_errstats) / sizeof (kstat_named_t);
341 343
342 344 if (bd->d_errstats != NULL)
343 345 return;
344 346
345 347 (void) snprintf(ks_module, sizeof (ks_module), "%serr",
346 348 ddi_driver_name(bd->d_dip));
347 349 (void) snprintf(ks_name, sizeof (ks_name), "%s%d,err",
348 350 ddi_driver_name(bd->d_dip), inst);
349 351
350 352 bd->d_errstats = kstat_create(ks_module, inst, ks_name, "device_error",
351 353 KSTAT_TYPE_NAMED, ndata, KSTAT_FLAG_PERSISTENT);
352 354
353 355 if (bd->d_errstats == NULL) {
354 356 /*
355 357 * Even if we cannot create the kstat, we create a
356 358 * scratch kstat. The reason for this is to ensure
357 359 * that we can update the kstat all of the time,
358 360 * without adding an extra branch instruction.
359 361 */
360 362 bd->d_kerr = kmem_zalloc(sizeof (struct bd_errstats),
361 363 KM_SLEEP);
362 364 bd->d_errmutex = kmem_zalloc(sizeof (kmutex_t), KM_SLEEP);
363 365 mutex_init(bd->d_errmutex, NULL, MUTEX_DRIVER, NULL);
364 366 } else {
365 367 if (bd->d_errstats->ks_lock == NULL) {
366 368 bd->d_errstats->ks_lock = kmem_zalloc(sizeof (kmutex_t),
367 369 KM_SLEEP);
368 370 mutex_init(bd->d_errstats->ks_lock, NULL, MUTEX_DRIVER,
369 371 NULL);
370 372 }
371 373
372 374 bd->d_errmutex = bd->d_errstats->ks_lock;
373 375 bd->d_kerr = (struct bd_errstats *)bd->d_errstats->ks_data;
374 376 }
375 377
376 378 kstat_named_init(&bd->d_kerr->bd_softerrs, "Soft Errors",
377 379 KSTAT_DATA_UINT32);
378 380 kstat_named_init(&bd->d_kerr->bd_harderrs, "Hard Errors",
379 381 KSTAT_DATA_UINT32);
380 382 kstat_named_init(&bd->d_kerr->bd_transerrs, "Transport Errors",
381 383 KSTAT_DATA_UINT32);
382 384
383 385 if (drive->d_model_len > 0) {
384 386 kstat_named_init(&bd->d_kerr->bd_model, "Model",
385 387 KSTAT_DATA_STRING);
386 388 } else {
387 389 kstat_named_init(&bd->d_kerr->bd_vid, "Vendor",
388 390 KSTAT_DATA_STRING);
389 391 kstat_named_init(&bd->d_kerr->bd_pid, "Product",
390 392 KSTAT_DATA_STRING);
391 393 }
392 394
393 395 kstat_named_init(&bd->d_kerr->bd_revision, "Revision",
394 396 KSTAT_DATA_STRING);
395 397 kstat_named_init(&bd->d_kerr->bd_serial, "Serial No",
396 398 KSTAT_DATA_STRING);
397 399 kstat_named_init(&bd->d_kerr->bd_capacity, "Size",
398 400 KSTAT_DATA_ULONGLONG);
399 401 kstat_named_init(&bd->d_kerr->bd_rq_media_err, "Media Error",
400 402 KSTAT_DATA_UINT32);
401 403 kstat_named_init(&bd->d_kerr->bd_rq_ntrdy_err, "Device Not Ready",
402 404 KSTAT_DATA_UINT32);
403 405 kstat_named_init(&bd->d_kerr->bd_rq_nodev_err, "No Device",
404 406 KSTAT_DATA_UINT32);
405 407 kstat_named_init(&bd->d_kerr->bd_rq_recov_err, "Recoverable",
406 408 KSTAT_DATA_UINT32);
407 409 kstat_named_init(&bd->d_kerr->bd_rq_illrq_err, "Illegal Request",
408 410 KSTAT_DATA_UINT32);
409 411 kstat_named_init(&bd->d_kerr->bd_rq_pfa_err,
410 412 "Predictive Failure Analysis", KSTAT_DATA_UINT32);
411 413
412 414 bd->d_errstats->ks_private = bd;
413 415
414 416 kstat_install(bd->d_errstats);
415 417 }
416 418
417 419 static void
418 420 bd_errstats_setstr(kstat_named_t *k, char *str, size_t len, char *alt)
419 421 {
420 422 char *tmp;
421 423
422 424 if (KSTAT_NAMED_STR_PTR(k) == NULL) {
423 425 if (len > 0) {
424 426 tmp = kmem_alloc(len + 1, KM_SLEEP);
425 427 (void) strlcpy(tmp, str, len + 1);
426 428 } else {
427 429 tmp = alt;
428 430 }
429 431
430 432 kstat_named_setstr(k, tmp);
431 433 }
432 434 }
433 435
434 436 static void
435 437 bd_init_errstats(bd_t *bd, bd_drive_t *drive)
436 438 {
437 439 struct bd_errstats *est = bd->d_kerr;
438 440
439 441 mutex_enter(bd->d_errmutex);
440 442
441 443 if (drive->d_model_len > 0 &&
442 444 KSTAT_NAMED_STR_PTR(&est->bd_model) == NULL) {
443 445 bd_errstats_setstr(&est->bd_model, drive->d_model,
444 446 drive->d_model_len, NULL);
445 447 } else {
446 448 bd_errstats_setstr(&est->bd_vid, drive->d_vendor,
447 449 drive->d_vendor_len, "Unknown ");
448 450 bd_errstats_setstr(&est->bd_pid, drive->d_product,
449 451 drive->d_product_len, "Unknown ");
450 452 }
451 453
452 454 bd_errstats_setstr(&est->bd_revision, drive->d_revision,
453 455 drive->d_revision_len, "0001");
454 456 bd_errstats_setstr(&est->bd_serial, drive->d_serial,
455 457 drive->d_serial_len, "0 ");
456 458
457 459 mutex_exit(bd->d_errmutex);
458 460 }
459 461
460 462 static int
461 463 bd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
462 464 {
463 465 int inst;
464 466 bd_handle_t hdl;
465 467 bd_t *bd;
466 468 bd_drive_t drive;
467 469 int rv;
468 470 char name[16];
469 471 char kcache[32];
470 472
471 473 switch (cmd) {
472 474 case DDI_ATTACH:
473 475 break;
474 476 case DDI_RESUME:
475 477 /* We don't do anything native for suspend/resume */
476 478 return (DDI_SUCCESS);
477 479 default:
478 480 return (DDI_FAILURE);
479 481 }
480 482
481 483 inst = ddi_get_instance(dip);
482 484 hdl = ddi_get_parent_data(dip);
483 485
484 486 (void) snprintf(name, sizeof (name), "%s%d",
485 487 ddi_driver_name(dip), ddi_get_instance(dip));
486 488 (void) snprintf(kcache, sizeof (kcache), "%s_xfer", name);
487 489
488 490 if (hdl == NULL) {
489 491 cmn_err(CE_WARN, "%s: missing parent data!", name);
490 492 return (DDI_FAILURE);
491 493 }
492 494
493 495 if (ddi_soft_state_zalloc(bd_state, inst) != DDI_SUCCESS) {
494 496 cmn_err(CE_WARN, "%s: unable to zalloc soft state!", name);
495 497 return (DDI_FAILURE);
496 498 }
497 499 bd = ddi_get_soft_state(bd_state, inst);
498 500
499 501 if (hdl->h_dma) {
500 502 bd->d_dma = *(hdl->h_dma);
501 503 bd->d_dma.dma_attr_granular =
502 504 max(DEV_BSIZE, bd->d_dma.dma_attr_granular);
503 505 bd->d_use_dma = B_TRUE;
504 506
505 507 if (bd->d_maxxfer &&
506 508 (bd->d_maxxfer != bd->d_dma.dma_attr_maxxfer)) {
507 509 cmn_err(CE_WARN,
508 510 "%s: inconsistent maximum transfer size!",
509 511 name);
510 512 /* We force it */
511 513 bd->d_maxxfer = bd->d_dma.dma_attr_maxxfer;
512 514 } else {
513 515 bd->d_maxxfer = bd->d_dma.dma_attr_maxxfer;
514 516 }
515 517 } else {
516 518 bd->d_use_dma = B_FALSE;
517 519 if (bd->d_maxxfer == 0) {
518 520 bd->d_maxxfer = 1024 * 1024;
519 521 }
520 522 }
521 523 bd->d_ops = hdl->h_ops;
522 524 bd->d_private = hdl->h_private;
523 525 bd->d_blkshift = 9; /* 512 bytes, to start */
524 526
525 527 if (bd->d_maxxfer % DEV_BSIZE) {
526 528 cmn_err(CE_WARN, "%s: maximum transfer misaligned!", name);
527 529 bd->d_maxxfer &= ~(DEV_BSIZE - 1);
528 530 }
529 531 if (bd->d_maxxfer < DEV_BSIZE) {
530 532 cmn_err(CE_WARN, "%s: maximum transfer size too small!", name);
531 533 ddi_soft_state_free(bd_state, inst);
532 534 return (DDI_FAILURE);
533 535 }
534 536
535 537 bd->d_dip = dip;
536 538 bd->d_handle = hdl;
537 539 hdl->h_bd = bd;
538 540 ddi_set_driver_private(dip, bd);
539 541
540 542 mutex_init(&bd->d_iomutex, NULL, MUTEX_DRIVER, NULL);
541 543 mutex_init(&bd->d_ocmutex, NULL, MUTEX_DRIVER, NULL);
542 544 mutex_init(&bd->d_statemutex, NULL, MUTEX_DRIVER, NULL);
543 545 cv_init(&bd->d_statecv, NULL, CV_DRIVER, NULL);
544 546
545 547 list_create(&bd->d_waitq, sizeof (bd_xfer_impl_t),
546 548 offsetof(struct bd_xfer_impl, i_linkage));
547 549 list_create(&bd->d_runq, sizeof (bd_xfer_impl_t),
548 550 offsetof(struct bd_xfer_impl, i_linkage));
549 551
550 552 bd->d_cache = kmem_cache_create(kcache, sizeof (bd_xfer_impl_t), 8,
551 553 bd_xfer_ctor, bd_xfer_dtor, NULL, bd, NULL, 0);
552 554
553 555 bd->d_ksp = kstat_create(ddi_driver_name(dip), inst, NULL, "disk",
554 556 KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT);
555 557 if (bd->d_ksp != NULL) {
556 558 bd->d_ksp->ks_lock = &bd->d_iomutex;
557 559 kstat_install(bd->d_ksp);
558 560 bd->d_kiop = bd->d_ksp->ks_data;
559 561 } else {
560 562 /*
561 563 * Even if we cannot create the kstat, we create a
562 564 * scratch kstat. The reason for this is to ensure
563 565 * that we can update the kstat all of the time,
564 566 * without adding an extra branch instruction.
565 567 */
566 568 bd->d_kiop = kmem_zalloc(sizeof (kstat_io_t), KM_SLEEP);
567 569 }
568 570
569 571 cmlb_alloc_handle(&bd->d_cmlbh);
570 572
571 573 bd->d_state = DKIO_NONE;
572 574
573 575 bzero(&drive, sizeof (drive));
574 576 bd->d_ops.o_drive_info(bd->d_private, &drive);
575 577 bd->d_qsize = drive.d_qsize;
576 578 bd->d_removable = drive.d_removable;
577 579 bd->d_hotpluggable = drive.d_hotpluggable;
578 580
579 581 if (drive.d_maxxfer && drive.d_maxxfer < bd->d_maxxfer)
580 582 bd->d_maxxfer = drive.d_maxxfer;
581 583
582 584 bd_create_inquiry_props(dip, &drive);
583 585
584 586 bd_create_errstats(bd, inst, &drive);
585 587 bd_init_errstats(bd, &drive);
586 588 bd_update_state(bd);
587 589
588 590 rv = cmlb_attach(dip, &bd_tg_ops, DTYPE_DIRECT,
589 591 bd->d_removable, bd->d_hotpluggable,
590 592 /*LINTED: E_BAD_PTR_CAST_ALIGN*/
591 593 *(uint64_t *)drive.d_eui64 != 0 ? DDI_NT_BLOCK_BLKDEV :
592 594 drive.d_lun >= 0 ? DDI_NT_BLOCK_CHAN : DDI_NT_BLOCK,
593 595 CMLB_FAKE_LABEL_ONE_PARTITION, bd->d_cmlbh, 0);
594 596 if (rv != 0) {
595 597 cmlb_free_handle(&bd->d_cmlbh);
596 598 kmem_cache_destroy(bd->d_cache);
597 599 mutex_destroy(&bd->d_iomutex);
598 600 mutex_destroy(&bd->d_ocmutex);
599 601 mutex_destroy(&bd->d_statemutex);
600 602 cv_destroy(&bd->d_statecv);
601 603 list_destroy(&bd->d_waitq);
602 604 list_destroy(&bd->d_runq);
603 605 if (bd->d_ksp != NULL) {
604 606 kstat_delete(bd->d_ksp);
605 607 bd->d_ksp = NULL;
606 608 } else {
607 609 kmem_free(bd->d_kiop, sizeof (kstat_io_t));
608 610 }
609 611 ddi_soft_state_free(bd_state, inst);
610 612 return (DDI_FAILURE);
611 613 }
612 614
613 615 if (bd->d_ops.o_devid_init != NULL) {
614 616 rv = bd->d_ops.o_devid_init(bd->d_private, dip, &bd->d_devid);
615 617 if (rv == DDI_SUCCESS) {
616 618 if (ddi_devid_register(dip, bd->d_devid) !=
617 619 DDI_SUCCESS) {
618 620 cmn_err(CE_WARN,
619 621 "%s: unable to register devid", name);
620 622 }
621 623 }
622 624 }
623 625
624 626 /*
625 627 * Add a zero-length attribute to tell the world we support
626 628 * kernel ioctls (for layered drivers). Also set up properties
627 629 * used by HAL to identify removable media.
628 630 */
629 631 (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
630 632 DDI_KERNEL_IOCTL, NULL, 0);
631 633 if (bd->d_removable) {
632 634 (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
633 635 "removable-media", NULL, 0);
634 636 }
635 637 if (bd->d_hotpluggable) {
636 638 (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
637 639 "hotpluggable", NULL, 0);
638 640 }
639 641
640 642 ddi_report_dev(dip);
641 643
642 644 return (DDI_SUCCESS);
643 645 }
644 646
645 647 static int
646 648 bd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
647 649 {
648 650 bd_t *bd;
649 651
650 652 bd = ddi_get_driver_private(dip);
651 653
652 654 switch (cmd) {
653 655 case DDI_DETACH:
654 656 break;
655 657 case DDI_SUSPEND:
656 658 /* We don't suspend, but our parent does */
657 659 return (DDI_SUCCESS);
658 660 default:
659 661 return (DDI_FAILURE);
660 662 }
661 663 if (bd->d_ksp != NULL) {
662 664 kstat_delete(bd->d_ksp);
663 665 bd->d_ksp = NULL;
664 666 } else {
665 667 kmem_free(bd->d_kiop, sizeof (kstat_io_t));
666 668 }
667 669
668 670 if (bd->d_errstats != NULL) {
669 671 kstat_delete(bd->d_errstats);
670 672 bd->d_errstats = NULL;
671 673 } else {
672 674 kmem_free(bd->d_kerr, sizeof (struct bd_errstats));
673 675 mutex_destroy(bd->d_errmutex);
674 676 }
675 677
676 678 cmlb_detach(bd->d_cmlbh, 0);
677 679 cmlb_free_handle(&bd->d_cmlbh);
678 680 if (bd->d_devid)
679 681 ddi_devid_free(bd->d_devid);
680 682 kmem_cache_destroy(bd->d_cache);
681 683 mutex_destroy(&bd->d_iomutex);
682 684 mutex_destroy(&bd->d_ocmutex);
683 685 mutex_destroy(&bd->d_statemutex);
684 686 cv_destroy(&bd->d_statecv);
685 687 list_destroy(&bd->d_waitq);
686 688 list_destroy(&bd->d_runq);
687 689 ddi_soft_state_free(bd_state, ddi_get_instance(dip));
688 690 return (DDI_SUCCESS);
689 691 }
690 692
691 693 static int
692 694 bd_xfer_ctor(void *buf, void *arg, int kmflag)
693 695 {
694 696 bd_xfer_impl_t *xi;
695 697 bd_t *bd = arg;
696 698 int (*dcb)(caddr_t);
697 699
698 700 if (kmflag == KM_PUSHPAGE || kmflag == KM_SLEEP) {
699 701 dcb = DDI_DMA_SLEEP;
700 702 } else {
701 703 dcb = DDI_DMA_DONTWAIT;
702 704 }
703 705
704 706 xi = buf;
705 707 bzero(xi, sizeof (*xi));
706 708 xi->i_bd = bd;
707 709
708 710 if (bd->d_use_dma) {
709 711 if (ddi_dma_alloc_handle(bd->d_dip, &bd->d_dma, dcb, NULL,
710 712 &xi->i_dmah) != DDI_SUCCESS) {
711 713 return (-1);
712 714 }
713 715 }
714 716
715 717 return (0);
716 718 }
717 719
718 720 static void
719 721 bd_xfer_dtor(void *buf, void *arg)
720 722 {
721 723 bd_xfer_impl_t *xi = buf;
722 724
723 725 _NOTE(ARGUNUSED(arg));
724 726
725 727 if (xi->i_dmah)
726 728 ddi_dma_free_handle(&xi->i_dmah);
727 729 xi->i_dmah = NULL;
728 730 }
729 731
730 732 static bd_xfer_impl_t *
731 733 bd_xfer_alloc(bd_t *bd, struct buf *bp, int (*func)(void *, bd_xfer_t *),
732 734 int kmflag)
733 735 {
734 736 bd_xfer_impl_t *xi;
735 737 int rv = 0;
736 738 int status;
737 739 unsigned dir;
738 740 int (*cb)(caddr_t);
739 741 size_t len;
740 742 uint32_t shift;
741 743
742 744 if (kmflag == KM_SLEEP) {
743 745 cb = DDI_DMA_SLEEP;
744 746 } else {
745 747 cb = DDI_DMA_DONTWAIT;
746 748 }
747 749
748 750 xi = kmem_cache_alloc(bd->d_cache, kmflag);
749 751 if (xi == NULL) {
750 752 bioerror(bp, ENOMEM);
751 753 return (NULL);
752 754 }
753 755
754 756 ASSERT(bp);
755 757
756 758 xi->i_bp = bp;
757 759 xi->i_func = func;
758 760 xi->i_blkno = bp->b_lblkno >> (bd->d_blkshift - DEV_BSHIFT);
759 761
760 762 if (bp->b_bcount == 0) {
761 763 xi->i_len = 0;
762 764 xi->i_nblks = 0;
763 765 xi->i_kaddr = NULL;
764 766 xi->i_resid = 0;
765 767 xi->i_num_win = 0;
766 768 goto done;
767 769 }
768 770
769 771 if (bp->b_flags & B_READ) {
770 772 dir = DDI_DMA_READ;
771 773 xi->i_func = bd->d_ops.o_read;
772 774 } else {
773 775 dir = DDI_DMA_WRITE;
774 776 xi->i_func = bd->d_ops.o_write;
775 777 }
776 778
777 779 shift = bd->d_blkshift;
778 780 xi->i_blkshift = shift;
779 781
780 782 if (!bd->d_use_dma) {
781 783 bp_mapin(bp);
782 784 rv = 0;
783 785 xi->i_offset = 0;
784 786 xi->i_num_win =
785 787 (bp->b_bcount + (bd->d_maxxfer - 1)) / bd->d_maxxfer;
786 788 xi->i_cur_win = 0;
787 789 xi->i_len = min(bp->b_bcount, bd->d_maxxfer);
788 790 xi->i_nblks = xi->i_len >> shift;
789 791 xi->i_kaddr = bp->b_un.b_addr;
790 792 xi->i_resid = bp->b_bcount;
791 793 } else {
792 794
793 795 /*
794 796 * We have to use consistent DMA if the address is misaligned.
795 797 */
796 798 if (((bp->b_flags & (B_PAGEIO | B_REMAPPED)) != B_PAGEIO) &&
797 799 ((uintptr_t)bp->b_un.b_addr & 0x7)) {
798 800 dir |= DDI_DMA_CONSISTENT | DDI_DMA_PARTIAL;
799 801 } else {
800 802 dir |= DDI_DMA_STREAMING | DDI_DMA_PARTIAL;
801 803 }
802 804
803 805 status = ddi_dma_buf_bind_handle(xi->i_dmah, bp, dir, cb,
804 806 NULL, &xi->i_dmac, &xi->i_ndmac);
805 807 switch (status) {
806 808 case DDI_DMA_MAPPED:
807 809 xi->i_num_win = 1;
808 810 xi->i_cur_win = 0;
809 811 xi->i_offset = 0;
810 812 xi->i_len = bp->b_bcount;
811 813 xi->i_nblks = xi->i_len >> shift;
812 814 xi->i_resid = bp->b_bcount;
813 815 rv = 0;
814 816 break;
815 817 case DDI_DMA_PARTIAL_MAP:
816 818 xi->i_cur_win = 0;
817 819
818 820 if ((ddi_dma_numwin(xi->i_dmah, &xi->i_num_win) !=
819 821 DDI_SUCCESS) ||
820 822 (ddi_dma_getwin(xi->i_dmah, 0, &xi->i_offset,
821 823 &len, &xi->i_dmac, &xi->i_ndmac) !=
822 824 DDI_SUCCESS) ||
823 825 (P2PHASE(len, (1U << shift)) != 0)) {
824 826 (void) ddi_dma_unbind_handle(xi->i_dmah);
825 827 rv = EFAULT;
826 828 goto done;
827 829 }
828 830 xi->i_len = len;
829 831 xi->i_nblks = xi->i_len >> shift;
830 832 xi->i_resid = bp->b_bcount;
831 833 rv = 0;
832 834 break;
833 835 case DDI_DMA_NORESOURCES:
834 836 rv = EAGAIN;
835 837 goto done;
836 838 case DDI_DMA_TOOBIG:
837 839 rv = EINVAL;
838 840 goto done;
839 841 case DDI_DMA_NOMAPPING:
840 842 case DDI_DMA_INUSE:
841 843 default:
842 844 rv = EFAULT;
843 845 goto done;
844 846 }
845 847 }
846 848
847 849 done:
848 850 if (rv != 0) {
849 851 kmem_cache_free(bd->d_cache, xi);
850 852 bioerror(bp, rv);
851 853 return (NULL);
852 854 }
853 855
854 856 return (xi);
855 857 }
856 858
857 859 static void
858 860 bd_xfer_free(bd_xfer_impl_t *xi)
859 861 {
860 862 if (xi->i_dmah) {
861 863 (void) ddi_dma_unbind_handle(xi->i_dmah);
862 864 }
863 865 kmem_cache_free(xi->i_bd->d_cache, xi);
864 866 }
865 867
866 868 static int
867 869 bd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
|
↓ open down ↓ |
683 lines elided |
↑ open up ↑ |
868 870 {
869 871 dev_t dev = *devp;
870 872 bd_t *bd;
871 873 minor_t part;
872 874 minor_t inst;
873 875 uint64_t mask;
874 876 boolean_t ndelay;
875 877 int rv;
876 878 diskaddr_t nblks;
877 879 diskaddr_t lba;
880 + int i;
878 881
879 882 _NOTE(ARGUNUSED(credp));
880 883
881 884 part = BDPART(dev);
882 885 inst = BDINST(dev);
883 886
884 887 if (otyp >= OTYPCNT)
885 888 return (EINVAL);
886 889
887 890 ndelay = (flag & (FNDELAY | FNONBLOCK)) ? B_TRUE : B_FALSE;
888 891
889 892 /*
890 893 * Block any DR events from changing the set of registered
891 894 * devices while we function.
892 895 */
893 896 rw_enter(&bd_lock, RW_READER);
894 897 if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
895 898 rw_exit(&bd_lock);
896 899 return (ENXIO);
897 900 }
898 901
899 902 mutex_enter(&bd->d_ocmutex);
900 903
901 904 ASSERT(part < 64);
902 905 mask = (1U << part);
903 906
904 907 bd_update_state(bd);
905 908
906 909 if (cmlb_validate(bd->d_cmlbh, 0, 0) != 0) {
907 910
908 911 /* non-blocking opens are allowed to succeed */
909 912 if (!ndelay) {
910 913 rv = ENXIO;
911 914 goto done;
912 915 }
913 916 } else if (cmlb_partinfo(bd->d_cmlbh, part, &nblks, &lba,
914 917 NULL, NULL, 0) == 0) {
915 918
916 919 /*
917 920 * We read the partinfo, verify valid ranges. If the
918 921 * partition is invalid, and we aren't blocking or
919 922 * doing a raw access, then fail. (Non-blocking and
920 923 * raw accesses can still succeed to allow a disk with
921 924 * bad partition data to opened by format and fdisk.)
922 925 */
923 926 if ((!nblks) && ((!ndelay) || (otyp != OTYP_CHR))) {
924 927 rv = ENXIO;
925 928 goto done;
926 929 }
927 930 } else if (!ndelay) {
928 931 /*
929 932 * cmlb_partinfo failed -- invalid partition or no
930 933 * disk label.
931 934 */
932 935 rv = ENXIO;
933 936 goto done;
934 937 }
935 938
936 939 if ((flag & FWRITE) && bd->d_rdonly) {
937 940 rv = EROFS;
938 941 goto done;
939 942 }
|
↓ open down ↓ |
52 lines elided |
↑ open up ↑ |
940 943
941 944 if ((bd->d_open_excl) & (mask)) {
942 945 rv = EBUSY;
943 946 goto done;
944 947 }
945 948 if (flag & FEXCL) {
946 949 if (bd->d_open_lyr[part]) {
947 950 rv = EBUSY;
948 951 goto done;
949 952 }
950 - for (int i = 0; i < OTYP_LYR; i++) {
953 + for (i = 0; i < OTYP_LYR; i++) {
951 954 if (bd->d_open_reg[i] & mask) {
952 955 rv = EBUSY;
953 956 goto done;
954 957 }
955 958 }
956 959 }
957 960
958 961 if (otyp == OTYP_LYR) {
959 962 bd->d_open_lyr[part]++;
960 963 } else {
961 964 bd->d_open_reg[otyp] |= mask;
962 965 }
963 966 if (flag & FEXCL) {
964 967 bd->d_open_excl |= mask;
965 968 }
966 969
967 970 rv = 0;
968 971 done:
969 972 mutex_exit(&bd->d_ocmutex);
970 973 rw_exit(&bd_lock);
971 974
972 975 return (rv);
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
973 976 }
974 977
975 978 static int
976 979 bd_close(dev_t dev, int flag, int otyp, cred_t *credp)
977 980 {
978 981 bd_t *bd;
979 982 minor_t inst;
980 983 minor_t part;
981 984 uint64_t mask;
982 985 boolean_t last = B_TRUE;
986 + int i;
983 987
984 988 _NOTE(ARGUNUSED(flag));
985 989 _NOTE(ARGUNUSED(credp));
986 990
987 991 part = BDPART(dev);
988 992 inst = BDINST(dev);
989 993
990 994 ASSERT(part < 64);
991 995 mask = (1U << part);
992 996
993 997 rw_enter(&bd_lock, RW_READER);
994 998
995 999 if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
996 1000 rw_exit(&bd_lock);
997 1001 return (ENXIO);
998 1002 }
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
999 1003
1000 1004 mutex_enter(&bd->d_ocmutex);
1001 1005 if (bd->d_open_excl & mask) {
1002 1006 bd->d_open_excl &= ~mask;
1003 1007 }
1004 1008 if (otyp == OTYP_LYR) {
1005 1009 bd->d_open_lyr[part]--;
1006 1010 } else {
1007 1011 bd->d_open_reg[otyp] &= ~mask;
1008 1012 }
1009 - for (int i = 0; i < 64; i++) {
1013 + for (i = 0; i < 64; i++) {
1010 1014 if (bd->d_open_lyr[part]) {
1011 1015 last = B_FALSE;
1012 1016 }
1013 1017 }
1014 - for (int i = 0; last && (i < OTYP_LYR); i++) {
1018 + for (i = 0; last && (i < OTYP_LYR); i++) {
1015 1019 if (bd->d_open_reg[i]) {
1016 1020 last = B_FALSE;
1017 1021 }
1018 1022 }
1019 1023 mutex_exit(&bd->d_ocmutex);
1020 1024
1021 1025 if (last) {
1022 1026 cmlb_invalidate(bd->d_cmlbh, 0);
1023 1027 }
1024 1028 rw_exit(&bd_lock);
1025 1029
1026 1030 return (0);
1027 1031 }
1028 1032
1029 1033 static int
1030 1034 bd_dump(dev_t dev, caddr_t caddr, daddr_t blkno, int nblk)
1031 1035 {
1032 1036 minor_t inst;
1033 1037 minor_t part;
1034 1038 diskaddr_t pstart;
1035 1039 diskaddr_t psize;
1036 1040 bd_t *bd;
1037 1041 bd_xfer_impl_t *xi;
1038 1042 buf_t *bp;
1039 1043 int rv;
1040 1044 uint32_t shift;
1041 1045 daddr_t d_blkno;
1042 1046 int d_nblk;
1043 1047
1044 1048 rw_enter(&bd_lock, RW_READER);
1045 1049
1046 1050 part = BDPART(dev);
1047 1051 inst = BDINST(dev);
1048 1052
1049 1053 if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
1050 1054 rw_exit(&bd_lock);
1051 1055 return (ENXIO);
1052 1056 }
1053 1057 shift = bd->d_blkshift;
1054 1058 d_blkno = blkno >> (shift - DEV_BSHIFT);
1055 1059 d_nblk = nblk >> (shift - DEV_BSHIFT);
1056 1060 /*
1057 1061 * do cmlb, but do it synchronously unless we already have the
1058 1062 * partition (which we probably should.)
1059 1063 */
1060 1064 if (cmlb_partinfo(bd->d_cmlbh, part, &psize, &pstart, NULL, NULL,
1061 1065 (void *)1)) {
1062 1066 rw_exit(&bd_lock);
1063 1067 return (ENXIO);
1064 1068 }
1065 1069
1066 1070 if ((d_blkno + d_nblk) > psize) {
1067 1071 rw_exit(&bd_lock);
1068 1072 return (EINVAL);
1069 1073 }
1070 1074 bp = getrbuf(KM_NOSLEEP);
1071 1075 if (bp == NULL) {
1072 1076 rw_exit(&bd_lock);
1073 1077 return (ENOMEM);
1074 1078 }
1075 1079
1076 1080 bp->b_bcount = nblk << DEV_BSHIFT;
1077 1081 bp->b_resid = bp->b_bcount;
1078 1082 bp->b_lblkno = blkno;
1079 1083 bp->b_un.b_addr = caddr;
1080 1084
1081 1085 xi = bd_xfer_alloc(bd, bp, bd->d_ops.o_write, KM_NOSLEEP);
1082 1086 if (xi == NULL) {
1083 1087 rw_exit(&bd_lock);
1084 1088 freerbuf(bp);
1085 1089 return (ENOMEM);
1086 1090 }
1087 1091 xi->i_blkno = d_blkno + pstart;
1088 1092 xi->i_flags = BD_XFER_POLL;
1089 1093 bd_submit(bd, xi);
1090 1094 rw_exit(&bd_lock);
1091 1095
1092 1096 /*
1093 1097 * Generally, we should have run this entirely synchronously
1094 1098 * at this point and the biowait call should be a no-op. If
1095 1099 * it didn't happen this way, it's a bug in the underlying
1096 1100 * driver not honoring BD_XFER_POLL.
1097 1101 */
1098 1102 (void) biowait(bp);
1099 1103 rv = geterror(bp);
1100 1104 freerbuf(bp);
1101 1105 return (rv);
1102 1106 }
1103 1107
1104 1108 void
1105 1109 bd_minphys(struct buf *bp)
1106 1110 {
1107 1111 minor_t inst;
1108 1112 bd_t *bd;
1109 1113 inst = BDINST(bp->b_edev);
1110 1114
1111 1115 bd = ddi_get_soft_state(bd_state, inst);
1112 1116
1113 1117 /*
1114 1118 * In a non-debug kernel, bd_strategy will catch !bd as
1115 1119 * well, and will fail nicely.
1116 1120 */
1117 1121 ASSERT(bd);
1118 1122
1119 1123 if (bp->b_bcount > bd->d_maxxfer)
1120 1124 bp->b_bcount = bd->d_maxxfer;
1121 1125 }
1122 1126
1123 1127 static int
1124 1128 bd_check_uio(dev_t dev, struct uio *uio)
1125 1129 {
1126 1130 bd_t *bd;
1127 1131 uint32_t shift;
1128 1132
1129 1133 if ((bd = ddi_get_soft_state(bd_state, BDINST(dev))) == NULL) {
1130 1134 return (ENXIO);
1131 1135 }
1132 1136
1133 1137 shift = bd->d_blkshift;
1134 1138 if ((P2PHASE(uio->uio_loffset, (1U << shift)) != 0) ||
1135 1139 (P2PHASE(uio->uio_iov->iov_len, (1U << shift)) != 0)) {
1136 1140 return (EINVAL);
1137 1141 }
1138 1142
1139 1143 return (0);
1140 1144 }
1141 1145
1142 1146 static int
1143 1147 bd_read(dev_t dev, struct uio *uio, cred_t *credp)
1144 1148 {
1145 1149 _NOTE(ARGUNUSED(credp));
1146 1150 int ret = bd_check_uio(dev, uio);
1147 1151 if (ret != 0) {
1148 1152 return (ret);
1149 1153 }
1150 1154 return (physio(bd_strategy, NULL, dev, B_READ, bd_minphys, uio));
1151 1155 }
1152 1156
1153 1157 static int
1154 1158 bd_write(dev_t dev, struct uio *uio, cred_t *credp)
1155 1159 {
1156 1160 _NOTE(ARGUNUSED(credp));
1157 1161 int ret = bd_check_uio(dev, uio);
1158 1162 if (ret != 0) {
1159 1163 return (ret);
1160 1164 }
1161 1165 return (physio(bd_strategy, NULL, dev, B_WRITE, bd_minphys, uio));
1162 1166 }
1163 1167
1164 1168 static int
1165 1169 bd_aread(dev_t dev, struct aio_req *aio, cred_t *credp)
1166 1170 {
1167 1171 _NOTE(ARGUNUSED(credp));
1168 1172 int ret = bd_check_uio(dev, aio->aio_uio);
1169 1173 if (ret != 0) {
1170 1174 return (ret);
1171 1175 }
1172 1176 return (aphysio(bd_strategy, anocancel, dev, B_READ, bd_minphys, aio));
1173 1177 }
1174 1178
1175 1179 static int
1176 1180 bd_awrite(dev_t dev, struct aio_req *aio, cred_t *credp)
1177 1181 {
1178 1182 _NOTE(ARGUNUSED(credp));
1179 1183 int ret = bd_check_uio(dev, aio->aio_uio);
1180 1184 if (ret != 0) {
1181 1185 return (ret);
1182 1186 }
1183 1187 return (aphysio(bd_strategy, anocancel, dev, B_WRITE, bd_minphys, aio));
1184 1188 }
1185 1189
1186 1190 static int
1187 1191 bd_strategy(struct buf *bp)
1188 1192 {
1189 1193 minor_t inst;
1190 1194 minor_t part;
1191 1195 bd_t *bd;
1192 1196 diskaddr_t p_lba;
1193 1197 diskaddr_t p_nblks;
1194 1198 diskaddr_t b_nblks;
1195 1199 bd_xfer_impl_t *xi;
1196 1200 uint32_t shift;
1197 1201 int (*func)(void *, bd_xfer_t *);
1198 1202 diskaddr_t lblkno;
1199 1203
1200 1204 part = BDPART(bp->b_edev);
1201 1205 inst = BDINST(bp->b_edev);
1202 1206
1203 1207 ASSERT(bp);
1204 1208
1205 1209 bp->b_resid = bp->b_bcount;
1206 1210
1207 1211 if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
1208 1212 bioerror(bp, ENXIO);
1209 1213 biodone(bp);
1210 1214 return (0);
1211 1215 }
1212 1216
1213 1217 if (cmlb_partinfo(bd->d_cmlbh, part, &p_nblks, &p_lba,
1214 1218 NULL, NULL, 0)) {
1215 1219 bioerror(bp, ENXIO);
1216 1220 biodone(bp);
1217 1221 return (0);
1218 1222 }
1219 1223
1220 1224 shift = bd->d_blkshift;
1221 1225 lblkno = bp->b_lblkno >> (shift - DEV_BSHIFT);
1222 1226 if ((P2PHASE(bp->b_lblkno, (1U << (shift - DEV_BSHIFT))) != 0) ||
1223 1227 (P2PHASE(bp->b_bcount, (1U << shift)) != 0) ||
1224 1228 (lblkno > p_nblks)) {
1225 1229 bioerror(bp, EINVAL);
1226 1230 biodone(bp);
1227 1231 return (0);
1228 1232 }
1229 1233 b_nblks = bp->b_bcount >> shift;
1230 1234 if ((lblkno == p_nblks) || (bp->b_bcount == 0)) {
1231 1235 biodone(bp);
1232 1236 return (0);
1233 1237 }
1234 1238
1235 1239 if ((b_nblks + lblkno) > p_nblks) {
1236 1240 bp->b_resid = ((lblkno + b_nblks - p_nblks) << shift);
1237 1241 bp->b_bcount -= bp->b_resid;
1238 1242 } else {
1239 1243 bp->b_resid = 0;
1240 1244 }
1241 1245 func = (bp->b_flags & B_READ) ? bd->d_ops.o_read : bd->d_ops.o_write;
1242 1246
1243 1247 xi = bd_xfer_alloc(bd, bp, func, KM_NOSLEEP);
1244 1248 if (xi == NULL) {
1245 1249 xi = bd_xfer_alloc(bd, bp, func, KM_PUSHPAGE);
1246 1250 }
1247 1251 if (xi == NULL) {
1248 1252 /* bd_request_alloc will have done bioerror */
1249 1253 biodone(bp);
1250 1254 return (0);
1251 1255 }
1252 1256 xi->i_blkno = lblkno + p_lba;
1253 1257
1254 1258 bd_submit(bd, xi);
1255 1259
1256 1260 return (0);
1257 1261 }
1258 1262
1259 1263 static int
1260 1264 bd_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp)
1261 1265 {
1262 1266 minor_t inst;
1263 1267 uint16_t part;
1264 1268 bd_t *bd;
1265 1269 void *ptr = (void *)arg;
1266 1270 int rv;
1267 1271
1268 1272 part = BDPART(dev);
1269 1273 inst = BDINST(dev);
1270 1274
1271 1275 if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
1272 1276 return (ENXIO);
1273 1277 }
1274 1278
1275 1279 rv = cmlb_ioctl(bd->d_cmlbh, dev, cmd, arg, flag, credp, rvalp, 0);
1276 1280 if (rv != ENOTTY)
1277 1281 return (rv);
1278 1282
1279 1283 if (rvalp != NULL) {
1280 1284 /* the return value of the ioctl is 0 by default */
1281 1285 *rvalp = 0;
1282 1286 }
1283 1287
1284 1288 switch (cmd) {
1285 1289 case DKIOCGMEDIAINFO: {
1286 1290 struct dk_minfo minfo;
1287 1291
1288 1292 /* make sure our state information is current */
1289 1293 bd_update_state(bd);
1290 1294 bzero(&minfo, sizeof (minfo));
1291 1295 minfo.dki_media_type = DK_FIXED_DISK;
1292 1296 minfo.dki_lbsize = (1U << bd->d_blkshift);
1293 1297 minfo.dki_capacity = bd->d_numblks;
1294 1298 if (ddi_copyout(&minfo, ptr, sizeof (minfo), flag)) {
1295 1299 return (EFAULT);
1296 1300 }
1297 1301 return (0);
1298 1302 }
1299 1303 case DKIOCGMEDIAINFOEXT: {
1300 1304 struct dk_minfo_ext miext;
1301 1305
1302 1306 /* make sure our state information is current */
1303 1307 bd_update_state(bd);
1304 1308 bzero(&miext, sizeof (miext));
1305 1309 miext.dki_media_type = DK_FIXED_DISK;
1306 1310 miext.dki_lbsize = (1U << bd->d_blkshift);
1307 1311 miext.dki_pbsize = (1U << bd->d_pblkshift);
1308 1312 miext.dki_capacity = bd->d_numblks;
1309 1313 if (ddi_copyout(&miext, ptr, sizeof (miext), flag)) {
1310 1314 return (EFAULT);
1311 1315 }
1312 1316 return (0);
1313 1317 }
1314 1318 case DKIOCINFO: {
1315 1319 struct dk_cinfo cinfo;
1316 1320 bzero(&cinfo, sizeof (cinfo));
1317 1321 cinfo.dki_ctype = DKC_BLKDEV;
1318 1322 cinfo.dki_cnum = ddi_get_instance(ddi_get_parent(bd->d_dip));
1319 1323 (void) snprintf(cinfo.dki_cname, sizeof (cinfo.dki_cname),
1320 1324 "%s", ddi_driver_name(ddi_get_parent(bd->d_dip)));
1321 1325 (void) snprintf(cinfo.dki_dname, sizeof (cinfo.dki_dname),
1322 1326 "%s", ddi_driver_name(bd->d_dip));
1323 1327 cinfo.dki_unit = inst;
1324 1328 cinfo.dki_flags = DKI_FMTVOL;
1325 1329 cinfo.dki_partition = part;
1326 1330 cinfo.dki_maxtransfer = bd->d_maxxfer / DEV_BSIZE;
1327 1331 cinfo.dki_addr = 0;
1328 1332 cinfo.dki_slave = 0;
1329 1333 cinfo.dki_space = 0;
1330 1334 cinfo.dki_prio = 0;
1331 1335 cinfo.dki_vec = 0;
1332 1336 if (ddi_copyout(&cinfo, ptr, sizeof (cinfo), flag)) {
1333 1337 return (EFAULT);
1334 1338 }
1335 1339 return (0);
1336 1340 }
1337 1341 case DKIOCREMOVABLE: {
1338 1342 int i;
1339 1343 i = bd->d_removable ? 1 : 0;
1340 1344 if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
1341 1345 return (EFAULT);
1342 1346 }
1343 1347 return (0);
1344 1348 }
1345 1349 case DKIOCHOTPLUGGABLE: {
1346 1350 int i;
1347 1351 i = bd->d_hotpluggable ? 1 : 0;
1348 1352 if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
1349 1353 return (EFAULT);
1350 1354 }
1351 1355 return (0);
1352 1356 }
1353 1357 case DKIOCREADONLY: {
1354 1358 int i;
1355 1359 i = bd->d_rdonly ? 1 : 0;
1356 1360 if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
1357 1361 return (EFAULT);
1358 1362 }
1359 1363 return (0);
1360 1364 }
1361 1365 case DKIOCSOLIDSTATE: {
1362 1366 int i;
1363 1367 i = bd->d_ssd ? 1 : 0;
1364 1368 if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
1365 1369 return (EFAULT);
1366 1370 }
1367 1371 return (0);
1368 1372 }
1369 1373 case DKIOCSTATE: {
1370 1374 enum dkio_state state;
1371 1375 if (ddi_copyin(ptr, &state, sizeof (state), flag)) {
1372 1376 return (EFAULT);
1373 1377 }
1374 1378 if ((rv = bd_check_state(bd, &state)) != 0) {
1375 1379 return (rv);
1376 1380 }
1377 1381 if (ddi_copyout(&state, ptr, sizeof (state), flag)) {
1378 1382 return (EFAULT);
1379 1383 }
1380 1384 return (0);
1381 1385 }
|
↓ open down ↓ |
357 lines elided |
↑ open up ↑ |
1382 1386 case DKIOCFLUSHWRITECACHE: {
1383 1387 struct dk_callback *dkc = NULL;
1384 1388
1385 1389 if (flag & FKIOCTL)
1386 1390 dkc = (void *)arg;
1387 1391
1388 1392 rv = bd_flush_write_cache(bd, dkc);
1389 1393 return (rv);
1390 1394 }
1391 1395
1396 + case MHIOCTKOWN:
1397 + {
1398 + return (bd_reserve(bd, BD_XFER_MHD_TKOWN));
1399 + }
1400 +
1401 + case MHIOCRELEASE:
1402 + {
1403 + return (bd_reserve(bd, BD_XFER_MHD_RELEASE));
1404 + }
1405 +
1406 + case MHIOCSTATUS:
1407 + {
1408 + rv = bd_reserve(bd, BD_XFER_MHD_STATUS);
1409 + if (rvalp != NULL)
1410 + *rvalp = rv == 0 ? 0: 1;
1411 + return (0);
1412 + }
1413 +
1414 + case MHIOCQRESERVE:
1415 + {
1416 + return (bd_reserve(bd, BD_XFER_MHD_QRESERVE));
1417 + }
1418 +
1419 + case MHIOCENFAILFAST:
1420 + {
1421 + return (bd_reserve(bd, BD_XFER_MHD_ENFAILFAST));
1422 + }
1423 +
1392 1424 default:
1393 1425 break;
1394 1426
1395 1427 }
1396 1428 return (ENOTTY);
1397 1429 }
1398 1430
1399 1431 static int
1400 1432 bd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
1401 1433 char *name, caddr_t valuep, int *lengthp)
1402 1434 {
1403 1435 bd_t *bd;
1404 1436
1405 1437 bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip));
1406 1438 if (bd == NULL)
1407 1439 return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1408 1440 name, valuep, lengthp));
1409 1441
1410 1442 return (cmlb_prop_op(bd->d_cmlbh, dev, dip, prop_op, mod_flags, name,
1411 1443 valuep, lengthp, BDPART(dev), 0));
1412 1444 }
1413 1445
1414 1446
1415 1447 static int
1416 1448 bd_tg_rdwr(dev_info_t *dip, uchar_t cmd, void *bufaddr, diskaddr_t start,
1417 1449 size_t length, void *tg_cookie)
1418 1450 {
1419 1451 bd_t *bd;
1420 1452 buf_t *bp;
1421 1453 bd_xfer_impl_t *xi;
1422 1454 int rv;
1423 1455 int (*func)(void *, bd_xfer_t *);
1424 1456 int kmflag;
1425 1457
1426 1458 /*
1427 1459 * If we are running in polled mode (such as during dump(9e)
1428 1460 * execution), then we cannot sleep for kernel allocations.
1429 1461 */
1430 1462 kmflag = tg_cookie ? KM_NOSLEEP : KM_SLEEP;
1431 1463
1432 1464 bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip));
1433 1465
1434 1466 if (P2PHASE(length, (1U << bd->d_blkshift)) != 0) {
1435 1467 /* We can only transfer whole blocks at a time! */
1436 1468 return (EINVAL);
1437 1469 }
1438 1470
1439 1471 if ((bp = getrbuf(kmflag)) == NULL) {
1440 1472 return (ENOMEM);
1441 1473 }
1442 1474
1443 1475 switch (cmd) {
1444 1476 case TG_READ:
1445 1477 bp->b_flags = B_READ;
1446 1478 func = bd->d_ops.o_read;
1447 1479 break;
1448 1480 case TG_WRITE:
1449 1481 bp->b_flags = B_WRITE;
1450 1482 func = bd->d_ops.o_write;
1451 1483 break;
1452 1484 default:
1453 1485 freerbuf(bp);
1454 1486 return (EINVAL);
1455 1487 }
1456 1488
1457 1489 bp->b_un.b_addr = bufaddr;
1458 1490 bp->b_bcount = length;
1459 1491 xi = bd_xfer_alloc(bd, bp, func, kmflag);
1460 1492 if (xi == NULL) {
1461 1493 rv = geterror(bp);
1462 1494 freerbuf(bp);
1463 1495 return (rv);
1464 1496 }
1465 1497 xi->i_flags = tg_cookie ? BD_XFER_POLL : 0;
1466 1498 xi->i_blkno = start;
1467 1499 bd_submit(bd, xi);
1468 1500 (void) biowait(bp);
1469 1501 rv = geterror(bp);
1470 1502 freerbuf(bp);
1471 1503
1472 1504 return (rv);
1473 1505 }
1474 1506
1475 1507 static int
1476 1508 bd_tg_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie)
1477 1509 {
1478 1510 bd_t *bd;
1479 1511
1480 1512 _NOTE(ARGUNUSED(tg_cookie));
1481 1513 bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip));
1482 1514
1483 1515 switch (cmd) {
1484 1516 case TG_GETPHYGEOM:
1485 1517 case TG_GETVIRTGEOM:
1486 1518 /*
1487 1519 * We don't have any "geometry" as such, let cmlb
1488 1520 * fabricate something.
1489 1521 */
1490 1522 return (ENOTTY);
1491 1523
1492 1524 case TG_GETCAPACITY:
1493 1525 bd_update_state(bd);
1494 1526 *(diskaddr_t *)arg = bd->d_numblks;
1495 1527 return (0);
1496 1528
1497 1529 case TG_GETBLOCKSIZE:
1498 1530 *(uint32_t *)arg = (1U << bd->d_blkshift);
1499 1531 return (0);
1500 1532
1501 1533 case TG_GETATTR:
1502 1534 /*
1503 1535 * It turns out that cmlb really doesn't do much for
1504 1536 * non-writable media, but lets make the information
1505 1537 * available for it in case it does more in the
1506 1538 * future. (The value is currently used for
1507 1539 * triggering special behavior for CD-ROMs.)
1508 1540 */
1509 1541 bd_update_state(bd);
1510 1542 ((tg_attribute_t *)arg)->media_is_writable =
1511 1543 bd->d_rdonly ? B_FALSE : B_TRUE;
1512 1544 ((tg_attribute_t *)arg)->media_is_solid_state = bd->d_ssd;
1513 1545 ((tg_attribute_t *)arg)->media_is_rotational = B_FALSE;
1514 1546 return (0);
1515 1547
1516 1548 default:
1517 1549 return (EINVAL);
1518 1550 }
1519 1551 }
1520 1552
1521 1553
1522 1554 static void
1523 1555 bd_sched(bd_t *bd)
1524 1556 {
1525 1557 bd_xfer_impl_t *xi;
1526 1558 struct buf *bp;
1527 1559 int rv;
1528 1560
1529 1561 mutex_enter(&bd->d_iomutex);
1530 1562
1531 1563 while ((bd->d_qactive < bd->d_qsize) &&
1532 1564 ((xi = list_remove_head(&bd->d_waitq)) != NULL)) {
1533 1565 bd->d_qactive++;
1534 1566 kstat_waitq_to_runq(bd->d_kiop);
1535 1567 list_insert_tail(&bd->d_runq, xi);
1536 1568
1537 1569 /*
1538 1570 * Submit the job to the driver. We drop the I/O mutex
1539 1571 * so that we can deal with the case where the driver
1540 1572 * completion routine calls back into us synchronously.
1541 1573 */
1542 1574
1543 1575 mutex_exit(&bd->d_iomutex);
1544 1576
1545 1577 rv = xi->i_func(bd->d_private, &xi->i_public);
1546 1578 if (rv != 0) {
1547 1579 bp = xi->i_bp;
1548 1580 bioerror(bp, rv);
1549 1581 biodone(bp);
1550 1582
1551 1583 atomic_inc_32(&bd->d_kerr->bd_transerrs.value.ui32);
1552 1584
1553 1585 mutex_enter(&bd->d_iomutex);
1554 1586 bd->d_qactive--;
1555 1587 kstat_runq_exit(bd->d_kiop);
1556 1588 list_remove(&bd->d_runq, xi);
1557 1589 bd_xfer_free(xi);
1558 1590 } else {
1559 1591 mutex_enter(&bd->d_iomutex);
1560 1592 }
1561 1593 }
1562 1594
1563 1595 mutex_exit(&bd->d_iomutex);
1564 1596 }
1565 1597
1566 1598 static void
1567 1599 bd_submit(bd_t *bd, bd_xfer_impl_t *xi)
1568 1600 {
1569 1601 mutex_enter(&bd->d_iomutex);
1570 1602 list_insert_tail(&bd->d_waitq, xi);
1571 1603 kstat_waitq_enter(bd->d_kiop);
1572 1604 mutex_exit(&bd->d_iomutex);
1573 1605
1574 1606 bd_sched(bd);
1575 1607 }
1576 1608
1577 1609 static void
1578 1610 bd_runq_exit(bd_xfer_impl_t *xi, int err)
1579 1611 {
1580 1612 bd_t *bd = xi->i_bd;
1581 1613 buf_t *bp = xi->i_bp;
1582 1614
1583 1615 mutex_enter(&bd->d_iomutex);
1584 1616 bd->d_qactive--;
1585 1617 kstat_runq_exit(bd->d_kiop);
1586 1618 list_remove(&bd->d_runq, xi);
1587 1619 mutex_exit(&bd->d_iomutex);
1588 1620
1589 1621 if (err == 0) {
1590 1622 if (bp->b_flags & B_READ) {
1591 1623 bd->d_kiop->reads++;
1592 1624 bd->d_kiop->nread += (bp->b_bcount - xi->i_resid);
1593 1625 } else {
1594 1626 bd->d_kiop->writes++;
1595 1627 bd->d_kiop->nwritten += (bp->b_bcount - xi->i_resid);
1596 1628 }
1597 1629 }
1598 1630 bd_sched(bd);
1599 1631 }
1600 1632
1601 1633 static void
1602 1634 bd_update_state(bd_t *bd)
1603 1635 {
1604 1636 enum dkio_state state = DKIO_INSERTED;
1605 1637 boolean_t docmlb = B_FALSE;
1606 1638 bd_media_t media;
1607 1639
1608 1640 bzero(&media, sizeof (media));
1609 1641
1610 1642 mutex_enter(&bd->d_statemutex);
1611 1643 if (bd->d_ops.o_media_info(bd->d_private, &media) != 0) {
1612 1644 bd->d_numblks = 0;
1613 1645 state = DKIO_EJECTED;
1614 1646 goto done;
1615 1647 }
1616 1648
1617 1649 if ((media.m_blksize < 512) ||
1618 1650 (!ISP2(media.m_blksize)) ||
1619 1651 (P2PHASE(bd->d_maxxfer, media.m_blksize))) {
1620 1652 cmn_err(CE_WARN, "%s%d: Invalid media block size (%d)",
1621 1653 ddi_driver_name(bd->d_dip), ddi_get_instance(bd->d_dip),
1622 1654 media.m_blksize);
1623 1655 /*
1624 1656 * We can't use the media, treat it as not present.
1625 1657 */
1626 1658 state = DKIO_EJECTED;
1627 1659 bd->d_numblks = 0;
1628 1660 goto done;
1629 1661 }
1630 1662
1631 1663 if (((1U << bd->d_blkshift) != media.m_blksize) ||
1632 1664 (bd->d_numblks != media.m_nblks)) {
1633 1665 /* Device size changed */
1634 1666 docmlb = B_TRUE;
1635 1667 }
1636 1668
1637 1669 bd->d_blkshift = ddi_ffs(media.m_blksize) - 1;
1638 1670 bd->d_pblkshift = bd->d_blkshift;
1639 1671 bd->d_numblks = media.m_nblks;
1640 1672 bd->d_rdonly = media.m_readonly;
1641 1673 bd->d_ssd = media.m_solidstate;
1642 1674
1643 1675 /*
1644 1676 * Only use the supplied physical block size if it is non-zero,
1645 1677 * greater or equal to the block size, and a power of 2. Ignore it
1646 1678 * if not, it's just informational and we can still use the media.
1647 1679 */
1648 1680 if ((media.m_pblksize != 0) &&
1649 1681 (media.m_pblksize >= media.m_blksize) &&
1650 1682 (ISP2(media.m_pblksize)))
1651 1683 bd->d_pblkshift = ddi_ffs(media.m_pblksize) - 1;
1652 1684
1653 1685 done:
1654 1686 if (state != bd->d_state) {
1655 1687 bd->d_state = state;
1656 1688 cv_broadcast(&bd->d_statecv);
1657 1689 docmlb = B_TRUE;
1658 1690 }
1659 1691 mutex_exit(&bd->d_statemutex);
1660 1692
1661 1693 bd->d_kerr->bd_capacity.value.ui64 = bd->d_numblks << bd->d_blkshift;
1662 1694
1663 1695 if (docmlb) {
1664 1696 if (state == DKIO_INSERTED) {
1665 1697 (void) cmlb_validate(bd->d_cmlbh, 0, 0);
1666 1698 } else {
1667 1699 cmlb_invalidate(bd->d_cmlbh, 0);
1668 1700 }
1669 1701 }
1670 1702 }
1671 1703
1672 1704 static int
1673 1705 bd_check_state(bd_t *bd, enum dkio_state *state)
1674 1706 {
1675 1707 clock_t when;
1676 1708
1677 1709 for (;;) {
1678 1710
1679 1711 bd_update_state(bd);
1680 1712
1681 1713 mutex_enter(&bd->d_statemutex);
1682 1714
1683 1715 if (bd->d_state != *state) {
1684 1716 *state = bd->d_state;
1685 1717 mutex_exit(&bd->d_statemutex);
1686 1718 break;
1687 1719 }
1688 1720
1689 1721 when = drv_usectohz(1000000);
1690 1722 if (cv_reltimedwait_sig(&bd->d_statecv, &bd->d_statemutex,
1691 1723 when, TR_CLOCK_TICK) == 0) {
1692 1724 mutex_exit(&bd->d_statemutex);
1693 1725 return (EINTR);
1694 1726 }
1695 1727
1696 1728 mutex_exit(&bd->d_statemutex);
1697 1729 }
1698 1730
1699 1731 return (0);
1700 1732 }
1701 1733
1702 1734 static int
1703 1735 bd_flush_write_cache_done(struct buf *bp)
1704 1736 {
1705 1737 struct dk_callback *dc = (void *)bp->b_private;
1706 1738
1707 1739 (*dc->dkc_callback)(dc->dkc_cookie, geterror(bp));
1708 1740 kmem_free(dc, sizeof (*dc));
1709 1741 freerbuf(bp);
1710 1742 return (0);
1711 1743 }
1712 1744
1713 1745 static int
1714 1746 bd_flush_write_cache(bd_t *bd, struct dk_callback *dkc)
1715 1747 {
1716 1748 buf_t *bp;
1717 1749 struct dk_callback *dc;
1718 1750 bd_xfer_impl_t *xi;
1719 1751 int rv;
1720 1752
1721 1753 if (bd->d_ops.o_sync_cache == NULL) {
1722 1754 return (ENOTSUP);
1723 1755 }
1724 1756 if ((bp = getrbuf(KM_SLEEP)) == NULL) {
1725 1757 return (ENOMEM);
1726 1758 }
1727 1759 bp->b_resid = 0;
1728 1760 bp->b_bcount = 0;
1729 1761
1730 1762 xi = bd_xfer_alloc(bd, bp, bd->d_ops.o_sync_cache, KM_SLEEP);
1731 1763 if (xi == NULL) {
1732 1764 rv = geterror(bp);
1733 1765 freerbuf(bp);
1734 1766 return (rv);
1735 1767 }
1736 1768
1737 1769 /* Make an asynchronous flush, but only if there is a callback */
1738 1770 if (dkc != NULL && dkc->dkc_callback != NULL) {
1739 1771 /* Make a private copy of the callback structure */
1740 1772 dc = kmem_alloc(sizeof (*dc), KM_SLEEP);
1741 1773 *dc = *dkc;
1742 1774 bp->b_private = dc;
|
↓ open down ↓ |
341 lines elided |
↑ open up ↑ |
1743 1775 bp->b_iodone = bd_flush_write_cache_done;
1744 1776
1745 1777 bd_submit(bd, xi);
1746 1778 return (0);
1747 1779 }
1748 1780
1749 1781 /* In case there is no callback, perform a synchronous flush */
1750 1782 bd_submit(bd, xi);
1751 1783 (void) biowait(bp);
1752 1784 rv = geterror(bp);
1785 + freerbuf(bp);
1786 +
1787 + return (rv);
1788 +}
1789 +
1790 +static int
1791 +bd_reserve(bd_t *bd, int flag)
1792 +{
1793 + buf_t *bp;
1794 + bd_xfer_impl_t *xi;
1795 + int rv;
1796 +
1797 + if (bd->d_ops.o_reserve == NULL) {
1798 + return (ENOTSUP);
1799 + }
1800 + if ((bp = getrbuf(KM_SLEEP)) == NULL) {
1801 + return (ENOMEM);
1802 + }
1803 + bp->b_resid = 0;
1804 + bp->b_bcount = 0;
1805 +
1806 + xi = bd_xfer_alloc(bd, bp, bd->d_ops.o_reserve, KM_SLEEP);
1807 + if (xi == NULL) {
1808 + rv = geterror(bp);
1809 + freerbuf(bp);
1810 + return (rv);
1811 + }
1812 +
1813 + xi->i_flags = flag;
1814 +
1815 + bd_submit(bd, xi);
1816 +
1817 + /* wait synchronously */
1818 + (void) biowait(bp);
1819 + rv = geterror(bp);
1753 1820 freerbuf(bp);
1754 1821
1755 1822 return (rv);
1756 1823 }
1757 1824
1758 1825 /*
1759 1826 * Nexus support.
1760 1827 */
1761 1828 int
1762 1829 bd_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
1763 1830 void *arg, void *result)
1764 1831 {
1765 1832 bd_handle_t hdl;
1766 1833
1767 1834 switch (ctlop) {
1768 1835 case DDI_CTLOPS_REPORTDEV:
1769 1836 cmn_err(CE_CONT, "?Block device: %s@%s, %s%d\n",
1770 1837 ddi_node_name(rdip), ddi_get_name_addr(rdip),
1771 1838 ddi_driver_name(rdip), ddi_get_instance(rdip));
1772 1839 return (DDI_SUCCESS);
1773 1840
1774 1841 case DDI_CTLOPS_INITCHILD:
1775 1842 hdl = ddi_get_parent_data((dev_info_t *)arg);
1776 1843 if (hdl == NULL) {
1777 1844 return (DDI_NOT_WELL_FORMED);
1778 1845 }
1779 1846 ddi_set_name_addr((dev_info_t *)arg, hdl->h_addr);
1780 1847 return (DDI_SUCCESS);
1781 1848
1782 1849 case DDI_CTLOPS_UNINITCHILD:
1783 1850 ddi_set_name_addr((dev_info_t *)arg, NULL);
1784 1851 ndi_prop_remove_all((dev_info_t *)arg);
1785 1852 return (DDI_SUCCESS);
1786 1853
1787 1854 default:
1788 1855 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
1789 1856 }
1790 1857 }
1791 1858
1792 1859 /*
1793 1860 * Functions for device drivers.
1794 1861 */
1795 1862 bd_handle_t
1796 1863 bd_alloc_handle(void *private, bd_ops_t *ops, ddi_dma_attr_t *dma, int kmflag)
1797 1864 {
1798 1865 bd_handle_t hdl;
1799 1866
1800 1867 hdl = kmem_zalloc(sizeof (*hdl), kmflag);
1801 1868 if (hdl != NULL) {
1802 1869 hdl->h_ops = *ops;
1803 1870 hdl->h_dma = dma;
1804 1871 hdl->h_private = private;
1805 1872 }
1806 1873
1807 1874 return (hdl);
1808 1875 }
1809 1876
1810 1877 void
1811 1878 bd_free_handle(bd_handle_t hdl)
1812 1879 {
1813 1880 kmem_free(hdl, sizeof (*hdl));
1814 1881 }
1815 1882
1816 1883 int
1817 1884 bd_attach_handle(dev_info_t *dip, bd_handle_t hdl)
1818 1885 {
1819 1886 dev_info_t *child;
1820 1887 bd_drive_t drive = { 0 };
1821 1888
1822 1889 /*
1823 1890 * It's not an error if bd_attach_handle() is called on a handle that
1824 1891 * already is attached. We just ignore the request to attach and return.
1825 1892 * This way drivers using blkdev don't have to keep track about blkdev
1826 1893 * state, they can just call this function to make sure it attached.
1827 1894 */
1828 1895 if (hdl->h_child != NULL) {
1829 1896 return (DDI_SUCCESS);
1830 1897 }
1831 1898
1832 1899 /* if drivers don't override this, make it assume none */
1833 1900 drive.d_lun = -1;
1834 1901 hdl->h_ops.o_drive_info(hdl->h_private, &drive);
1835 1902
1836 1903 hdl->h_parent = dip;
1837 1904 hdl->h_name = "blkdev";
1838 1905
1839 1906 /*LINTED: E_BAD_PTR_CAST_ALIGN*/
1840 1907 if (*(uint64_t *)drive.d_eui64 != 0) {
1841 1908 if (drive.d_lun >= 0) {
1842 1909 (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr),
1843 1910 "w%02X%02X%02X%02X%02X%02X%02X%02X,%X",
1844 1911 drive.d_eui64[0], drive.d_eui64[1],
1845 1912 drive.d_eui64[2], drive.d_eui64[3],
1846 1913 drive.d_eui64[4], drive.d_eui64[5],
1847 1914 drive.d_eui64[6], drive.d_eui64[7], drive.d_lun);
1848 1915 } else {
1849 1916 (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr),
1850 1917 "w%02X%02X%02X%02X%02X%02X%02X%02X",
1851 1918 drive.d_eui64[0], drive.d_eui64[1],
1852 1919 drive.d_eui64[2], drive.d_eui64[3],
1853 1920 drive.d_eui64[4], drive.d_eui64[5],
1854 1921 drive.d_eui64[6], drive.d_eui64[7]);
1855 1922 }
1856 1923 } else {
1857 1924 if (drive.d_lun >= 0) {
1858 1925 (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr),
1859 1926 "%X,%X", drive.d_target, drive.d_lun);
1860 1927 } else {
1861 1928 (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr),
1862 1929 "%X", drive.d_target);
1863 1930 }
1864 1931 }
1865 1932
1866 1933 if (ndi_devi_alloc(dip, hdl->h_name, (pnode_t)DEVI_SID_NODEID,
1867 1934 &child) != NDI_SUCCESS) {
1868 1935 cmn_err(CE_WARN, "%s%d: unable to allocate node %s@%s",
1869 1936 ddi_driver_name(dip), ddi_get_instance(dip),
1870 1937 "blkdev", hdl->h_addr);
1871 1938 return (DDI_FAILURE);
1872 1939 }
1873 1940
1874 1941 ddi_set_parent_data(child, hdl);
1875 1942 hdl->h_child = child;
1876 1943
1877 1944 if (ndi_devi_online(child, 0) == NDI_FAILURE) {
1878 1945 cmn_err(CE_WARN, "%s%d: failed bringing node %s@%s online",
1879 1946 ddi_driver_name(dip), ddi_get_instance(dip),
1880 1947 hdl->h_name, hdl->h_addr);
1881 1948 (void) ndi_devi_free(child);
1882 1949 return (DDI_FAILURE);
1883 1950 }
1884 1951
1885 1952 return (DDI_SUCCESS);
1886 1953 }
1887 1954
1888 1955 int
1889 1956 bd_detach_handle(bd_handle_t hdl)
1890 1957 {
1891 1958 int circ;
1892 1959 int rv;
1893 1960 char *devnm;
1894 1961
1895 1962 /*
1896 1963 * It's not an error if bd_detach_handle() is called on a handle that
1897 1964 * already is detached. We just ignore the request to detach and return.
1898 1965 * This way drivers using blkdev don't have to keep track about blkdev
1899 1966 * state, they can just call this function to make sure it detached.
1900 1967 */
1901 1968 if (hdl->h_child == NULL) {
1902 1969 return (DDI_SUCCESS);
1903 1970 }
1904 1971 ndi_devi_enter(hdl->h_parent, &circ);
1905 1972 if (i_ddi_node_state(hdl->h_child) < DS_INITIALIZED) {
1906 1973 rv = ddi_remove_child(hdl->h_child, 0);
1907 1974 } else {
1908 1975 devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
1909 1976 (void) ddi_deviname(hdl->h_child, devnm);
1910 1977 (void) devfs_clean(hdl->h_parent, devnm + 1, DV_CLEAN_FORCE);
1911 1978 rv = ndi_devi_unconfig_one(hdl->h_parent, devnm + 1, NULL,
1912 1979 NDI_DEVI_REMOVE | NDI_UNCONFIG);
1913 1980 kmem_free(devnm, MAXNAMELEN + 1);
1914 1981 }
1915 1982 if (rv == 0) {
1916 1983 hdl->h_child = NULL;
1917 1984 }
1918 1985
1919 1986 ndi_devi_exit(hdl->h_parent, circ);
1920 1987 return (rv == NDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
1921 1988 }
1922 1989
1923 1990 void
1924 1991 bd_xfer_done(bd_xfer_t *xfer, int err)
1925 1992 {
1926 1993 bd_xfer_impl_t *xi = (void *)xfer;
1927 1994 buf_t *bp = xi->i_bp;
1928 1995 int rv = DDI_SUCCESS;
1929 1996 bd_t *bd = xi->i_bd;
1930 1997 size_t len;
1931 1998
1932 1999 if (err != 0) {
1933 2000 bd_runq_exit(xi, err);
1934 2001 atomic_inc_32(&bd->d_kerr->bd_harderrs.value.ui32);
1935 2002
1936 2003 bp->b_resid += xi->i_resid;
1937 2004 bd_xfer_free(xi);
1938 2005 bioerror(bp, err);
1939 2006 biodone(bp);
1940 2007 return;
1941 2008 }
1942 2009
1943 2010 xi->i_cur_win++;
1944 2011 xi->i_resid -= xi->i_len;
1945 2012
1946 2013 if (xi->i_resid == 0) {
1947 2014 /* Job completed succcessfully! */
1948 2015 bd_runq_exit(xi, 0);
1949 2016
1950 2017 bd_xfer_free(xi);
1951 2018 biodone(bp);
1952 2019 return;
1953 2020 }
1954 2021
1955 2022 xi->i_blkno += xi->i_nblks;
1956 2023
1957 2024 if (bd->d_use_dma) {
1958 2025 /* More transfer still pending... advance to next DMA window. */
1959 2026 rv = ddi_dma_getwin(xi->i_dmah, xi->i_cur_win,
1960 2027 &xi->i_offset, &len, &xi->i_dmac, &xi->i_ndmac);
1961 2028 } else {
1962 2029 /* Advance memory window. */
1963 2030 xi->i_kaddr += xi->i_len;
1964 2031 xi->i_offset += xi->i_len;
1965 2032 len = min(bp->b_bcount - xi->i_offset, bd->d_maxxfer);
1966 2033 }
1967 2034
1968 2035
1969 2036 if ((rv != DDI_SUCCESS) ||
1970 2037 (P2PHASE(len, (1U << xi->i_blkshift)) != 0)) {
1971 2038 bd_runq_exit(xi, EFAULT);
1972 2039
1973 2040 bp->b_resid += xi->i_resid;
1974 2041 bd_xfer_free(xi);
1975 2042 bioerror(bp, EFAULT);
1976 2043 biodone(bp);
1977 2044 return;
1978 2045 }
1979 2046 xi->i_len = len;
1980 2047 xi->i_nblks = len >> xi->i_blkshift;
1981 2048
1982 2049 /* Submit next window to hardware. */
1983 2050 rv = xi->i_func(bd->d_private, &xi->i_public);
1984 2051 if (rv != 0) {
1985 2052 bd_runq_exit(xi, rv);
1986 2053
1987 2054 atomic_inc_32(&bd->d_kerr->bd_transerrs.value.ui32);
1988 2055
1989 2056 bp->b_resid += xi->i_resid;
1990 2057 bd_xfer_free(xi);
1991 2058 bioerror(bp, rv);
1992 2059 biodone(bp);
1993 2060 }
1994 2061 }
1995 2062
1996 2063 void
1997 2064 bd_error(bd_xfer_t *xfer, int error)
1998 2065 {
1999 2066 bd_xfer_impl_t *xi = (void *)xfer;
2000 2067 bd_t *bd = xi->i_bd;
2001 2068
2002 2069 switch (error) {
2003 2070 case BD_ERR_MEDIA:
2004 2071 atomic_inc_32(&bd->d_kerr->bd_rq_media_err.value.ui32);
2005 2072 break;
2006 2073 case BD_ERR_NTRDY:
2007 2074 atomic_inc_32(&bd->d_kerr->bd_rq_ntrdy_err.value.ui32);
2008 2075 break;
2009 2076 case BD_ERR_NODEV:
2010 2077 atomic_inc_32(&bd->d_kerr->bd_rq_nodev_err.value.ui32);
2011 2078 break;
2012 2079 case BD_ERR_RECOV:
2013 2080 atomic_inc_32(&bd->d_kerr->bd_rq_recov_err.value.ui32);
2014 2081 break;
2015 2082 case BD_ERR_ILLRQ:
2016 2083 atomic_inc_32(&bd->d_kerr->bd_rq_illrq_err.value.ui32);
2017 2084 break;
2018 2085 case BD_ERR_PFA:
2019 2086 atomic_inc_32(&bd->d_kerr->bd_rq_pfa_err.value.ui32);
2020 2087 break;
2021 2088 default:
2022 2089 cmn_err(CE_PANIC, "bd_error: unknown error type %d", error);
2023 2090 break;
2024 2091 }
2025 2092 }
2026 2093
2027 2094 void
2028 2095 bd_state_change(bd_handle_t hdl)
2029 2096 {
2030 2097 bd_t *bd;
2031 2098
2032 2099 if ((bd = hdl->h_bd) != NULL) {
2033 2100 bd_update_state(bd);
2034 2101 }
2035 2102 }
2036 2103
2037 2104 void
2038 2105 bd_mod_init(struct dev_ops *devops)
2039 2106 {
2040 2107 static struct bus_ops bd_bus_ops = {
2041 2108 BUSO_REV, /* busops_rev */
2042 2109 nullbusmap, /* bus_map */
2043 2110 NULL, /* bus_get_intrspec (OBSOLETE) */
2044 2111 NULL, /* bus_add_intrspec (OBSOLETE) */
2045 2112 NULL, /* bus_remove_intrspec (OBSOLETE) */
2046 2113 i_ddi_map_fault, /* bus_map_fault */
2047 2114 NULL, /* bus_dma_map (OBSOLETE) */
2048 2115 ddi_dma_allochdl, /* bus_dma_allochdl */
2049 2116 ddi_dma_freehdl, /* bus_dma_freehdl */
2050 2117 ddi_dma_bindhdl, /* bus_dma_bindhdl */
2051 2118 ddi_dma_unbindhdl, /* bus_dma_unbindhdl */
2052 2119 ddi_dma_flush, /* bus_dma_flush */
2053 2120 ddi_dma_win, /* bus_dma_win */
2054 2121 ddi_dma_mctl, /* bus_dma_ctl */
2055 2122 bd_bus_ctl, /* bus_ctl */
2056 2123 ddi_bus_prop_op, /* bus_prop_op */
2057 2124 NULL, /* bus_get_eventcookie */
2058 2125 NULL, /* bus_add_eventcall */
2059 2126 NULL, /* bus_remove_eventcall */
2060 2127 NULL, /* bus_post_event */
2061 2128 NULL, /* bus_intr_ctl (OBSOLETE) */
2062 2129 NULL, /* bus_config */
2063 2130 NULL, /* bus_unconfig */
2064 2131 NULL, /* bus_fm_init */
2065 2132 NULL, /* bus_fm_fini */
2066 2133 NULL, /* bus_fm_access_enter */
2067 2134 NULL, /* bus_fm_access_exit */
2068 2135 NULL, /* bus_power */
2069 2136 NULL, /* bus_intr_op */
2070 2137 };
2071 2138
2072 2139 devops->devo_bus_ops = &bd_bus_ops;
2073 2140
2074 2141 /*
2075 2142 * NB: The device driver is free to supply its own
2076 2143 * character entry device support.
2077 2144 */
2078 2145 }
2079 2146
2080 2147 void
2081 2148 bd_mod_fini(struct dev_ops *devops)
2082 2149 {
2083 2150 devops->devo_bus_ops = NULL;
2084 2151 }
|
↓ open down ↓ |
322 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX