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