diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/sun4v/io/ds_common.c | 50 | ||||
-rw-r--r-- | usr/src/uts/sun4v/io/ds_drv.c | 7 | ||||
-rw-r--r-- | usr/src/uts/sun4v/sys/ds_impl.h | 2 |
3 files changed, 43 insertions, 16 deletions
diff --git a/usr/src/uts/sun4v/io/ds_common.c b/usr/src/uts/sun4v/io/ds_common.c index ac6c2d8d23..8b91b26e6e 100644 --- a/usr/src/uts/sun4v/io/ds_common.c +++ b/usr/src/uts/sun4v/io/ds_common.c @@ -407,6 +407,7 @@ ds_ldc_fini(ds_port_t *port) char ebuf[DS_EBUFSIZE]; ASSERT(port->state >= DS_PORT_LDC_INIT); + ASSERT(MUTEX_HELD(&port->lock)); DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: ldc_id=%ld" DS_EOL, PORTID(port), __func__, port->ldc.id); @@ -429,6 +430,10 @@ ds_ldc_fini(ds_port_t *port) return (rv); } + port->ldc.id = (uint64_t)-1; + port->ldc.hdl = NULL; + port->ldc.state = 0; + return (rv); } @@ -459,7 +464,13 @@ ds_recv_msg(ds_port_t *port, caddr_t msgp, size_t *sizep) nbytes = bytes_left; - if ((rv = ldc_read(port->ldc.hdl, msgp, &nbytes)) != 0) { + mutex_enter(&port->lock); + if (port->ldc.state == LDC_UP) { + rv = ldc_read(port->ldc.hdl, msgp, &nbytes); + } else + rv = ENXIO; + mutex_exit(&port->lock); + if (rv != 0) { if (rv == ECONNRESET) { break; } else if (rv != EAGAIN) { @@ -537,7 +548,15 @@ ds_handle_recv(void *arg) mutex_enter(&port->rcv_lock); - while (((rv = ldc_chkq(port->ldc.hdl, &hasdata)) == 0) && hasdata) { + for (;;) { + mutex_enter(&port->lock); + if (port->ldc.state == LDC_UP) { + rv = ldc_chkq(port->ldc.hdl, &hasdata); + } else + rv = ENXIO; + mutex_exit(&port->lock); + if (rv != 0 || !hasdata) + break; DS_DBG(CE_NOTE, "ds@%lx: %s: reading next message" DS_EOL, PORTID(port), __func__); @@ -680,7 +699,13 @@ ds_send_msg(ds_port_t *port, caddr_t msg, size_t msglen) mutex_enter(&port->tx_lock); do { - if ((rv = ldc_write(port->ldc.hdl, currp, &msglen)) != 0) { + mutex_enter(&port->lock); + if (port->ldc.state == LDC_UP) { + rv = ldc_write(port->ldc.hdl, currp, &msglen); + } else + rv = ENXIO; + mutex_exit(&port->lock); + if (rv != 0) { if (rv == ECONNRESET) { mutex_exit(&port->tx_lock); ds_handle_down_reset_events(port); @@ -1397,6 +1422,7 @@ ds_handle_unreg_req(ds_port_t *port, caddr_t buf, size_t len) char *msg; size_t msglen; size_t explen = DS_MSG_LEN(ds_unreg_req_t); + boolean_t is_up; /* sanity check the incoming message */ if (len != explen) { @@ -1415,10 +1441,15 @@ ds_handle_unreg_req(ds_port_t *port, caddr_t buf, size_t len) ((svc = ds_find_clnt_svc_by_hdl_port(req->svc_handle, port)) == NULL && ((svc = ds_get_svc(req->svc_handle)) == NULL || svc->port != port))) { + mutex_exit(&ds_svcs.lock); + mutex_enter(&port->lock); + is_up = (port->ldc.state == LDC_UP); + mutex_exit(&port->lock); + if (!is_up) + return; cmn_err(CE_WARN, "ds@%lx: <unreg_req: invalid handle 0x%llx" DS_EOL, PORTID(port), (u_longlong_t)req->svc_handle); ds_send_unreg_nack(port, req->svc_handle); - mutex_exit(&ds_svcs.lock); return; } @@ -2731,16 +2762,11 @@ ds_port_common_init(ds_port_t *port) } void -ds_port_common_fini(ds_port_t *port, int is_fini) +ds_port_common_fini(ds_port_t *port) { - port->state = DS_PORT_FREE; + ASSERT(MUTEX_HELD(&port->lock)); - if (is_fini && (port->flags & DS_PORT_MUTEX_INITED) != 0) { - mutex_destroy(&port->lock); - mutex_destroy(&port->tx_lock); - mutex_destroy(&port->rcv_lock); - port->flags &= ~DS_PORT_MUTEX_INITED; - } + port->state = DS_PORT_FREE; DS_PORTSET_DEL(ds_allports, port->id); diff --git a/usr/src/uts/sun4v/io/ds_drv.c b/usr/src/uts/sun4v/io/ds_drv.c index ee21387df7..34caf542d0 100644 --- a/usr/src/uts/sun4v/io/ds_drv.c +++ b/usr/src/uts/sun4v/io/ds_drv.c @@ -817,6 +817,7 @@ ds_add_port(uint64_t port_id, uint64_t ldc_id, ds_domain_hdl_t dhdl, return (0); } +/* ARGSUSED */ int ds_remove_port(uint64_t port_id, int is_fini) { @@ -839,8 +840,6 @@ ds_remove_port(uint64_t port_id, int is_fini) (void) ds_ldc_fini(port); } - mutex_exit(&port->lock); - if (port->domain_name) { DS_FREE(port->domain_name, strlen(port->domain_name) + 1); port->domain_name = NULL; @@ -848,7 +847,9 @@ ds_remove_port(uint64_t port_id, int is_fini) port->domain_hdl = DS_DHDL_INVALID; /* clean up the port structure */ - ds_port_common_fini(port, is_fini); + ds_port_common_fini(port); + + mutex_exit(&port->lock); return (0); } diff --git a/usr/src/uts/sun4v/sys/ds_impl.h b/usr/src/uts/sun4v/sys/ds_impl.h index ab88cd9533..a2a06d21a3 100644 --- a/usr/src/uts/sun4v/sys/ds_impl.h +++ b/usr/src/uts/sun4v/sys/ds_impl.h @@ -468,7 +468,7 @@ ds_svc_t *ds_get_svc(ds_svc_hdl_t hdl); /* port utilities */ void ds_port_common_init(ds_port_t *port); -void ds_port_common_fini(ds_port_t *port, int is_fini); +void ds_port_common_fini(ds_port_t *port); /* misc utilities */ ds_vers_check_t ds_vers_isvalid(ds_ver_t *vers, int nvers); |