Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/1394/targets/av1394/av1394_async.c
+++ new/usr/src/uts/common/io/1394/targets/av1394/av1394_async.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, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
|
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 - * Copyright (c) 2014, Joyent, Inc. All rights reserved.
28 + * Copyright 2017 Joyent, Inc.
29 29 */
30 30
31 31 /*
32 32 * av1394 asynchronous module
33 33 */
34 34 #include <sys/stat.h>
35 35 #include <sys/file.h>
36 36 #include <sys/ddi.h>
37 37 #include <sys/sunddi.h>
38 38 #include <sys/1394/targets/av1394/av1394_impl.h>
39 39
40 40 /* configuration routines */
41 41 static void av1394_async_cleanup(av1394_inst_t *, int);
42 42 static int av1394_async_create_minor_node(av1394_inst_t *);
43 43 static void av1394_async_remove_minor_node(av1394_inst_t *);
44 44 static int av1394_async_update_targetinfo(av1394_inst_t *);
45 45 static int av1394_async_db2arq_type(int);
46 46 static void av1394_async_putbq(av1394_queue_t *, mblk_t *);
47 47
48 48 static int av1394_ioctl_arq_get_ibuf_size(av1394_inst_t *, void *, int);
49 49 static int av1394_ioctl_arq_set_ibuf_size(av1394_inst_t *, void *, int);
50 50
51 51 #define AV1394_TNF_ENTER(func) \
52 52 TNF_PROBE_0_DEBUG(func##_enter, AV1394_TNF_ASYNC_STACK, "");
53 53
54 54 #define AV1394_TNF_EXIT(func) \
55 55 TNF_PROBE_0_DEBUG(func##_exit, AV1394_TNF_ASYNC_STACK, "");
56 56
57 57 /* tunables */
58 58 int av1394_ibuf_size_default = 64 * 1024; /* default ibuf size */
59 59 int av1394_ibuf_size_max = 1024 * 1024; /* max ibuf size */
60 60
61 61 /*
62 62 *
63 63 * --- configuration entry points
64 64 *
65 65 */
66 66 int
67 67 av1394_async_attach(av1394_inst_t *avp)
68 68 {
69 69 av1394_async_t *ap = &avp->av_a;
70 70 ddi_iblock_cookie_t ibc = avp->av_attachinfo.iblock_cookie;
71 71
72 72 AV1394_TNF_ENTER(av1394_async_attach);
73 73
74 74 mutex_init(&ap->a_mutex, NULL, MUTEX_DRIVER, ibc);
75 75 av1394_initq(&ap->a_rq, ibc, av1394_ibuf_size_default);
76 76
77 77 if (av1394_fcp_attach(avp) != DDI_SUCCESS) {
78 78 av1394_async_cleanup(avp, 1);
79 79 AV1394_TNF_EXIT(av1394_async_attach);
80 80 return (DDI_FAILURE);
81 81 }
82 82
83 83 if (av1394_cfgrom_init(avp) != DDI_SUCCESS) {
84 84 av1394_async_cleanup(avp, 2);
85 85 AV1394_TNF_EXIT(av1394_async_attach);
86 86 return (DDI_FAILURE);
87 87 }
88 88
89 89 if (av1394_async_create_minor_node(avp) != DDI_SUCCESS) {
90 90 av1394_async_cleanup(avp, 3);
91 91 AV1394_TNF_EXIT(av1394_async_attach);
92 92 return (DDI_FAILURE);
93 93 }
94 94
95 95 if (av1394_async_update_targetinfo(avp) != DDI_SUCCESS) {
96 96 av1394_async_cleanup(avp, 4);
97 97 AV1394_TNF_EXIT(av1394_async_attach);
98 98 return (DDI_FAILURE);
99 99 }
100 100
101 101 AV1394_TNF_EXIT(av1394_async_attach);
102 102 return (DDI_SUCCESS);
103 103 }
104 104
105 105 void
106 106 av1394_async_detach(av1394_inst_t *avp)
107 107 {
108 108 AV1394_TNF_ENTER(av1394_async_detach);
109 109
110 110 av1394_async_cleanup(avp, AV1394_CLEANUP_LEVEL_MAX);
111 111
112 112 AV1394_TNF_EXIT(av1394_async_detach);
113 113 }
114 114
115 115 void
116 116 av1394_async_bus_reset(av1394_inst_t *avp)
117 117 {
118 118 av1394_async_t *ap = &avp->av_a;
119 119 mblk_t *bp;
120 120
121 121 AV1394_TNF_ENTER(av1394_async_bus_reset);
122 122
123 123 (void) av1394_async_update_targetinfo(avp);
124 124
125 125 mutex_enter(&ap->a_mutex);
126 126 if (ap->a_nopen > 0) {
127 127 mutex_exit(&ap->a_mutex);
128 128 return;
129 129 }
130 130 mutex_exit(&ap->a_mutex);
131 131
132 132 /* queue up a bus reset message */
133 133 if ((bp = allocb(1, BPRI_HI)) == NULL) {
134 134 TNF_PROBE_0(av1394_async_bus_reset_error_allocb,
135 135 AV1394_TNF_ASYNC_ERROR, "");
136 136 } else {
137 137 DB_TYPE(bp) = AV1394_M_BUS_RESET;
138 138 av1394_async_putq_rq(avp, bp);
139 139 }
140 140
141 141 AV1394_TNF_EXIT(av1394_async_bus_reset);
142 142 }
143 143
144 144 int
145 145 av1394_async_cpr_resume(av1394_inst_t *avp)
146 146 {
147 147 int ret;
148 148
149 149 AV1394_TNF_ENTER(av1394_async_cpr_resume);
150 150
151 151 ret = av1394_async_update_targetinfo(avp);
152 152
153 153 AV1394_TNF_EXIT(av1394_async_cpr_resume);
154 154 return (ret);
155 155 }
156 156
157 157 void
158 158 av1394_async_reconnect(av1394_inst_t *avp)
159 159 {
160 160 AV1394_TNF_ENTER(av1394_async_reconnect);
161 161
162 162 (void) av1394_async_update_targetinfo(avp);
163 163
164 164 AV1394_TNF_EXIT(av1394_async_reconnect);
165 165 }
166 166
167 167 int
168 168 av1394_async_open(av1394_inst_t *avp, int flag)
169 169 {
170 170 av1394_async_t *ap = &avp->av_a;
171 171
172 172 AV1394_TNF_ENTER(av1394_async_open);
173 173
174 174 mutex_enter(&ap->a_mutex);
175 175 if (ap->a_nopen == 0) {
176 176 ap->a_pollevents = 0;
177 177 }
178 178 ap->a_nopen++;
179 179 ap->a_oflag = flag;
180 180 mutex_exit(&ap->a_mutex);
181 181
182 182 AV1394_TNF_EXIT(av1394_async_open);
183 183 return (0);
184 184 }
185 185
186 186 /*ARGSUSED*/
187 187 int
188 188 av1394_async_close(av1394_inst_t *avp, int flag)
189 189 {
190 190 av1394_async_t *ap = &avp->av_a;
191 191
192 192 AV1394_TNF_ENTER(av1394_async_close);
193 193
194 194 av1394_cfgrom_close(avp);
195 195
196 196 av1394_flushq(&ap->a_rq);
197 197
198 198 mutex_enter(&ap->a_mutex);
199 199 ap->a_nopen = 0;
200 200 ap->a_pollevents = 0;
201 201 mutex_exit(&ap->a_mutex);
202 202
203 203 AV1394_TNF_EXIT(av1394_async_close);
204 204 return (0);
205 205 }
206 206
207 207 int
208 208 av1394_async_read(av1394_inst_t *avp, struct uio *uiop)
209 209 {
210 210 av1394_async_t *ap = &avp->av_a;
211 211 av1394_queue_t *q = &ap->a_rq;
212 212 iec61883_arq_t arq;
213 213 int ret = 0;
214 214 mblk_t *mp;
215 215 int dbtype;
216 216 int len;
217 217
218 218 AV1394_TNF_ENTER(av1394_async_read);
219 219
220 220 /* copyout as much as we can */
221 221 while ((uiop->uio_resid > 0) && (ret == 0)) {
222 222 /*
223 223 * if data is available, copy it out. otherwise wait until
224 224 * data arrives, unless opened with non-blocking flag
225 225 */
226 226 if ((mp = av1394_getq(q)) == NULL) {
227 227 if (ap->a_oflag & FNDELAY) {
228 228 AV1394_TNF_EXIT(av1394_async_read);
229 229 return (EAGAIN);
230 230 }
231 231 if (av1394_qwait_sig(q) <= 0) {
232 232 ret = EINTR;
233 233 }
234 234 continue;
235 235 }
236 236 dbtype = AV1394_DBTYPE(mp);
237 237
238 238 /* generate and copyout ARQ header, if not already */
239 239 if (!AV1394_IS_NOHDR(mp)) {
240 240 /* headers cannot be partially read */
241 241 if (uiop->uio_resid < sizeof (arq)) {
242 242 av1394_async_putbq(q, mp);
243 243 ret = EINVAL;
244 244 break;
245 245 }
246 246
247 247 arq.arq_type = av1394_async_db2arq_type(dbtype);
248 248 arq.arq_len = MBLKL(mp);
249 249 arq.arq_data.octlet = 0;
250 250
251 251 /* copy ARQ-embedded data */
252 252 len = min(arq.arq_len, sizeof (arq.arq_data));
253 253 bcopy(mp->b_rptr, &arq.arq_data.buf[0], len);
254 254
255 255 /* copyout the ARQ */
256 256 ret = uiomove(&arq, sizeof (arq), UIO_READ, uiop);
257 257 if (ret != 0) {
258 258 av1394_async_putbq(q, mp);
259 259 break;
260 260 }
261 261 mp->b_rptr += len;
262 262 AV1394_MARK_NOHDR(mp);
263 263 }
264 264
265 265 /* any data left? */
266 266 if (MBLKL(mp) == 0) {
267 267 freemsg(mp);
268 268 continue;
269 269 }
270 270
271 271 /* now we have some data and some user buffer space to fill */
272 272 len = min(uiop->uio_resid, MBLKL(mp));
273 273 if (len > 0) {
274 274 ret = uiomove(mp->b_rptr, len, UIO_READ, uiop);
275 275 if (ret != 0) {
276 276 av1394_async_putbq(q, mp);
277 277 break;
278 278 }
279 279 mp->b_rptr += len;
280 280 }
281 281
282 282 /* save the rest of the data for later */
283 283 if (MBLKL(mp) > 0) {
284 284 av1394_async_putbq(q, mp);
285 285 }
286 286 }
287 287
288 288 AV1394_TNF_EXIT(av1394_async_read);
289 289 return (0);
290 290 }
291 291
292 292 int
293 293 av1394_async_write(av1394_inst_t *avp, struct uio *uiop)
294 294 {
295 295 iec61883_arq_t arq;
296 296 int ret;
297 297
298 298 AV1394_TNF_ENTER(av1394_async_write);
299 299
300 300 /* all data should arrive in ARQ format */
301 301 while (uiop->uio_resid >= sizeof (arq)) {
302 302 if ((ret = uiomove(&arq, sizeof (arq), UIO_WRITE, uiop)) != 0) {
303 303 break;
304 304 }
305 305
306 306 switch (arq.arq_type) {
307 307 case IEC61883_ARQ_FCP_CMD:
308 308 case IEC61883_ARQ_FCP_RESP:
309 309 ret = av1394_fcp_write(avp, &arq, uiop);
310 310 break;
311 311 default:
312 312 ret = EINVAL;
313 313 }
314 314 if (ret != 0) {
315 315 break;
|
↓ open down ↓ |
277 lines elided |
↑ open up ↑ |
316 316 }
317 317 }
318 318
319 319 AV1394_TNF_EXIT(av1394_async_write);
320 320 return (ret);
321 321 }
322 322
323 323 /*ARGSUSED*/
324 324 int
325 325 av1394_async_ioctl(av1394_inst_t *avp, int cmd, intptr_t arg, int mode,
326 - int *rvalp)
326 + int *rvalp)
327 327 {
328 328 int ret = EINVAL;
329 329
330 330 AV1394_TNF_ENTER(av1394_async_ioctl);
331 331
332 332 switch (cmd) {
333 333 case IEC61883_ARQ_GET_IBUF_SIZE:
334 334 ret = av1394_ioctl_arq_get_ibuf_size(avp, (void *)arg, mode);
335 335 break;
336 336 case IEC61883_ARQ_SET_IBUF_SIZE:
337 337 ret = av1394_ioctl_arq_set_ibuf_size(avp, (void *)arg, mode);
338 338 break;
339 339 case IEC61883_NODE_GET_BUS_NAME:
340 340 ret = av1394_ioctl_node_get_bus_name(avp, (void *)arg, mode);
341 341 break;
342 342 case IEC61883_NODE_GET_UID:
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
343 343 ret = av1394_ioctl_node_get_uid(avp, (void *)arg, mode);
344 344 break;
345 345 case IEC61883_NODE_GET_TEXT_LEAF:
346 346 ret = av1394_ioctl_node_get_text_leaf(avp, (void *)arg, mode);
347 347 }
348 348
349 349 AV1394_TNF_EXIT(av1394_async_ioctl);
350 350 return (ret);
351 351 }
352 352
353 -/*ARGSUSED*/
354 353 int
355 354 av1394_async_poll(av1394_inst_t *avp, short events, int anyyet, short *reventsp,
356 - struct pollhead **phpp)
355 + struct pollhead **phpp)
357 356 {
358 357 av1394_async_t *ap = &avp->av_a;
359 358 av1394_queue_t *rq = &ap->a_rq;
360 359
361 360 AV1394_TNF_ENTER(av1394_async_poll);
362 361
363 - if (events & POLLIN) {
364 - if (av1394_peekq(rq))
362 + if (events & (POLLIN | POLLET)) {
363 + if ((events & POLLIN) && av1394_peekq(rq)) {
365 364 *reventsp |= POLLIN;
365 + }
366 366
367 367 if ((!*reventsp && !anyyet) || (events & POLLET)) {
368 368 mutex_enter(&ap->a_mutex);
369 - ap->a_pollevents |= POLLIN;
369 + if (events & POLLIN) {
370 + ap->a_pollevents |= POLLIN;
371 + }
370 372 *phpp = &ap->a_pollhead;
371 373 mutex_exit(&ap->a_mutex);
372 374 }
373 375 }
374 376
375 377 AV1394_TNF_EXIT(av1394_async_poll);
376 378 return (0);
377 379 }
378 380
379 381
380 382 /*
381 383 * put a message on the read queue, take care of polling
382 384 */
383 385 void
384 386 av1394_async_putq_rq(av1394_inst_t *avp, mblk_t *mp)
385 387 {
386 388 av1394_async_t *ap = &avp->av_a;
387 389
388 390 if (!av1394_putq(&ap->a_rq, mp)) {
389 391 freemsg(mp);
390 392 TNF_PROBE_0(av1394_async_putq_rq_error_putq,
391 393 AV1394_TNF_ASYNC_ERROR, "");
392 394 } else {
393 395 mutex_enter(&ap->a_mutex);
394 396 if (ap->a_pollevents & POLLIN) {
395 397 ap->a_pollevents &= ~POLLIN;
396 398 mutex_exit(&ap->a_mutex);
397 399 pollwakeup(&ap->a_pollhead, POLLIN);
398 400 } else {
399 401 mutex_exit(&ap->a_mutex);
400 402 }
401 403 }
402 404 }
403 405
404 406 /*
405 407 *
406 408 * --- configuration routines
407 409 *
408 410 * av1394_async_cleanup()
409 411 * Cleanup after attach
410 412 */
411 413 static void
412 414 av1394_async_cleanup(av1394_inst_t *avp, int level)
413 415 {
414 416 av1394_async_t *ap = &avp->av_a;
415 417
416 418 ASSERT((level > 0) && (level <= AV1394_CLEANUP_LEVEL_MAX));
417 419
418 420 switch (level) {
419 421 default:
420 422 av1394_async_remove_minor_node(avp);
421 423 /* FALLTHRU */
422 424 case 3:
423 425 av1394_cfgrom_fini(avp);
424 426 /* FALLTHRU */
425 427 case 2:
426 428 av1394_fcp_detach(avp);
427 429 /* FALLTHRU */
428 430 case 1:
429 431 av1394_destroyq(&ap->a_rq);
430 432 mutex_destroy(&ap->a_mutex);
431 433 }
432 434 }
433 435
434 436 /*
435 437 * av1394_async_create_minor_node()
436 438 * Create async minor node
437 439 */
438 440 static int
439 441 av1394_async_create_minor_node(av1394_inst_t *avp)
440 442 {
441 443 int ret;
442 444
443 445 ret = ddi_create_minor_node(avp->av_dip, "async",
444 446 S_IFCHR, AV1394_ASYNC_INST2MINOR(avp->av_instance),
445 447 DDI_NT_AV_ASYNC, NULL);
446 448 if (ret != DDI_SUCCESS) {
447 449 TNF_PROBE_0(av1394_async_create_minor_node_error,
448 450 AV1394_TNF_ASYNC_ERROR, "");
449 451 }
450 452 return (ret);
451 453 }
452 454
453 455 /*
454 456 * av1394_async_remove_minor_node()
455 457 * Remove async minor node
456 458 */
457 459 static void
458 460 av1394_async_remove_minor_node(av1394_inst_t *avp)
459 461 {
460 462 ddi_remove_minor_node(avp->av_dip, "async");
461 463 }
462 464
463 465 /*
464 466 * av1394_async_update_targetinfo()
465 467 * Retrieve target info and bus generation
466 468 */
467 469 static int
468 470 av1394_async_update_targetinfo(av1394_inst_t *avp)
469 471 {
470 472 av1394_async_t *ap = &avp->av_a;
471 473 uint_t bg;
472 474 int ret;
473 475
474 476 mutex_enter(&avp->av_mutex);
475 477 bg = avp->av_attachinfo.localinfo.bus_generation;
476 478 mutex_exit(&avp->av_mutex);
477 479
478 480 mutex_enter(&ap->a_mutex);
479 481 ret = t1394_get_targetinfo(avp->av_t1394_hdl, bg, 0, &ap->a_targetinfo);
480 482 ap->a_bus_generation = bg;
481 483 mutex_exit(&ap->a_mutex);
482 484
483 485 return (ret);
484 486 }
485 487
486 488 static int
487 489 av1394_async_db2arq_type(int dbtype)
488 490 {
489 491 int arq_type;
490 492
491 493 switch (dbtype) {
492 494 case AV1394_M_FCP_RESP:
493 495 arq_type = IEC61883_ARQ_FCP_RESP;
494 496 break;
495 497 case AV1394_M_FCP_CMD:
496 498 arq_type = IEC61883_ARQ_FCP_CMD;
497 499 break;
498 500 case AV1394_M_BUS_RESET:
499 501 arq_type = IEC61883_ARQ_BUS_RESET;
500 502 break;
501 503 default:
502 504 ASSERT(0); /* cannot happen */
503 505 }
504 506 return (arq_type);
505 507 }
506 508
507 509 static void
508 510 av1394_async_putbq(av1394_queue_t *q, mblk_t *mp)
509 511 {
510 512 if (!av1394_putbq(q, mp)) {
511 513 freemsg(mp);
512 514 TNF_PROBE_0(av1394_async_putbq_error,
513 515 AV1394_TNF_ASYNC_ERROR, "");
514 516 }
515 517 }
516 518
517 519 /*ARGSUSED*/
518 520 static int
519 521 av1394_ioctl_arq_get_ibuf_size(av1394_inst_t *avp, void *arg, int mode)
520 522 {
521 523 av1394_async_t *ap = &avp->av_a;
522 524 int sz;
523 525 int ret = 0;
524 526
525 527 AV1394_TNF_ENTER(av1394_ioctl_arq_get_ibuf_size);
526 528
527 529 sz = av1394_getmaxq(&ap->a_rq);
528 530
529 531 if (ddi_copyout(&sz, arg, sizeof (sz), mode) != 0) {
530 532 ret = EFAULT;
531 533 }
532 534
533 535 AV1394_TNF_EXIT(av1394_ioctl_arq_get_ibuf_size);
534 536 return (ret);
535 537 }
536 538
537 539 /*ARGSUSED*/
538 540 static int
539 541 av1394_ioctl_arq_set_ibuf_size(av1394_inst_t *avp, void *arg, int mode)
540 542 {
541 543 av1394_async_t *ap = &avp->av_a;
542 544 int sz;
543 545 int ret = 0;
544 546
545 547 AV1394_TNF_ENTER(av1394_ioctl_arq_set_ibuf_size);
546 548
547 549 sz = (int)(intptr_t)arg;
548 550
549 551 if ((sz < 0) || (sz > av1394_ibuf_size_max)) {
550 552 ret = EINVAL;
551 553 } else {
552 554 av1394_setmaxq(&ap->a_rq, sz);
553 555 }
554 556
555 557 AV1394_TNF_EXIT(av1394_ioctl_arq_set_ibuf_size);
556 558 return (ret);
557 559 }
|
↓ open down ↓ |
178 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX