diff options
| author | lm66018 <none@none> | 2006-06-02 07:47:46 -0700 |
|---|---|---|
| committer | lm66018 <none@none> | 2006-06-02 07:47:46 -0700 |
| commit | 8e6a2a040587479821d1e682a28bcef7e75f19a6 (patch) | |
| tree | 6b09b06afed1b71c8d225dc76d30e3ad22c10040 /usr/src | |
| parent | 297a2ad14ba0591f210adbe7bb5c9f70af7fe56a (diff) | |
| download | illumos-joyent-8e6a2a040587479821d1e682a28bcef7e75f19a6.tar.gz | |
6423207 Misc vntsd help messages
6424288 Guest domain allows user to change the ethernet address
6424330 retry ldc_up() during transmit if the channel is not up, in vnet driver
6428613 assertion failure in vdc as a result of DKIOCFLUSHWRITECACHE ioctl call
6431479 mismerge in hsvc introduced by 6391870
6431822 vds/vdc should not reference C macros __DATE__ or __TIME__
6431874 vdc sets the max transfer size incorrectly
6432364 preallocate tx buffers in vnet
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/cmd/vntsd/cmd.c | 24 | ||||
| -rw-r--r-- | usr/src/cmd/vntsd/console.c | 126 | ||||
| -rw-r--r-- | usr/src/uts/sun4v/io/vdc.c | 194 | ||||
| -rw-r--r-- | usr/src/uts/sun4v/io/vds.c | 4 | ||||
| -rw-r--r-- | usr/src/uts/sun4v/io/vnet.c | 7 | ||||
| -rw-r--r-- | usr/src/uts/sun4v/io/vnet_gen.c | 243 | ||||
| -rw-r--r-- | usr/src/uts/sun4v/os/hsvc.c | 7 | ||||
| -rw-r--r-- | usr/src/uts/sun4v/sys/vnet_gen.h | 7 |
8 files changed, 322 insertions, 290 deletions
diff --git a/usr/src/cmd/vntsd/cmd.c b/usr/src/cmd/vntsd/cmd.c index faabebd613..c39ef03399 100644 --- a/usr/src/cmd/vntsd/cmd.c +++ b/usr/src/cmd/vntsd/cmd.c @@ -41,12 +41,12 @@ * HT * * Vntsd special commands are: - * send break (~#) - * exit (~.) - * force write access (~w) - * cycle console down (~n) - * cycle console up (~p) - * help (~?) + * Send break (~#) + * Exit (~.) + * Force write access (~w) + * Console next (~n) + * Console previous (~p) + * Help (~?) */ #include <stdio.h> @@ -200,22 +200,22 @@ static int daemon_cmd_help(vntsd_client_t *clientp); static esctable_t etable[] = { /* send a break to vcc */ - {'#', "send break", genbrk}, + {'#', "Send break", genbrk}, /* exit */ - {'.', "exit from this console", (e_func_t)client_exit}, + {'.', "Exit from this console", (e_func_t)client_exit}, /* acquire write access */ - {'w', "force write access", acquire_write}, + {'w', "Force write access", acquire_write}, /* connect to next console in queue */ - {'n', "console down", (e_func_t)console_forward}, + {'n', "Console next", (e_func_t)console_forward}, /* connect to previous console in queue */ - {'p', "console up", (e_func_t)console_backward}, + {'p', "Console previous", (e_func_t)console_backward}, /* help must be next to last */ - {'?', "_", daemon_cmd_help}, + {'?', "Help", daemon_cmd_help}, /* table terminator */ {0, 0, 0} diff --git a/usr/src/cmd/vntsd/console.c b/usr/src/cmd/vntsd/console.c index 4b7c145e0e..caff15357a 100644 --- a/usr/src/cmd/vntsd/console.c +++ b/usr/src/cmd/vntsd/console.c @@ -183,7 +183,7 @@ display_help(vntsd_client_t *clientp) * messages for single character commands. Do not translate the * character before the --. */ - bufp = gettext("h -- this help)"); + bufp = gettext("h -- this help"); if ((rv = vntsd_write_line(clientp, bufp)) != VNTSD_SUCCESS) { return (rv); @@ -207,7 +207,8 @@ display_help(vntsd_client_t *clientp) * "identifier" and both occurrences should be translated. */ - bufp = gettext("[c[c ]]{id} -- connect to console of domain {id}"); + bufp = gettext("c{id}, n{name} -- connect to a console of domain {id}" + " or domain {name}"); if ((rv = vntsd_write_line(clientp, bufp)) != VNTSD_SUCCESS) { return (rv); @@ -216,12 +217,38 @@ display_help(vntsd_client_t *clientp) return (VNTSD_SUCCESS); } +/* cons_by_name() - find a console structure according to a ldom's name */ +static boolean_t +cons_by_name(vntsd_cons_t *consp, char *name) +{ + if (consp->status & VNTSD_CONS_DELETED) { + return (B_FALSE); + } + return (strcmp(consp->domain_name, name) == 0); +} + +/* name_to_cons_no - convert a ldom's name to its consno */ +static int +name_to_cons_no(vntsd_group_t *groupp, char *name) +{ + vntsd_cons_t *consp; + + consp = (vntsd_cons_t *)vntsd_que_find(groupp->conspq, + (compare_func_t)cons_by_name, name); + + if (consp == NULL) { + return (-1); + } + + return (consp->cons_no); +} + /* select a console to connect */ static int -select_cons(vntsd_group_t *groupp, int num_cons, vntsd_cons_t **consp, +select_cons(vntsd_group_t *groupp, vntsd_cons_t **consp, vntsd_client_t *clientp, char c) { - int cons_no = -2; + int cons_no = -1; int n; int i; char buf[VNTSD_LINE_LEN]; @@ -237,24 +264,9 @@ select_cons(vntsd_group_t *groupp, int num_cons, vntsd_cons_t **consp, } (void) mutex_unlock(&groupp->lock); - if (num_cons == 1) { - /* by pass selecting console */ - *consp = (vntsd_cons_t *)(groupp->conspq->handle); - return (VNTSD_SUCCESS); - } + /* c{id} or n{name} */ - if (isdigit(c)) { - /* {id} input */ - cons_no = c - '0'; - } else if (c == 'c') { - /* c{id} or c {id} input */ - cons_no = -1; - } else if (!isspace(c)) { - return (VNTSD_ERR_INVALID_INPUT); - } - - /* get client selections */ n = VNTSD_LINE_LEN; if ((rv = vntsd_read_line(clientp, buf, &n)) != VNTSD_SUCCESS) { @@ -263,25 +275,39 @@ select_cons(vntsd_group_t *groupp, int num_cons, vntsd_cons_t **consp, /* parse command */ for (i = 0; i < n; i++) { - if (cons_no == -1) { - /* c{id} */ + switch (c) { + + case 'c': + /* c{id} or c {id} */ + if (isspace(buf[i])) { + continue; + } + + if (!isdigit(buf[i])) { + return (VNTSD_ERR_INVALID_INPUT); + } + cons_no = atoi(buf + i); break; - } - if (isspace(buf[i]) && cons_no == -2) { - /* skip space */ - continue; - } + case 'n': + /* n{name) or n {name} */ + if (isspace(buf[i])) { + continue; + } - if (buf[i] == 'c') { - /* c{id} or c {id} */ - cons_no = -1; - } else if (buf[i] == CR) { + buf[n-1] = 0; + cons_no = name_to_cons_no(groupp, buf+i); break; - } else { + + default: + /* should never get here */ return (VNTSD_ERR_INVALID_INPUT); + } + + /* got user selection */ + break; } if (cons_no < 0) { @@ -650,11 +676,11 @@ vntsd_console_thread(vntsd_thr_arg_t *argp) } if (snprintf(prompt, sizeof (prompt), - "%s-vnts-%s: h,l,{id},c{id},c {id},q:", + "%s-vnts-%s: h, l, c{id}, n{name}, q:", buf, groupp->group_name) >= sizeof (prompt)) { /* long prompt doesn't fit, use short one */ (void) snprintf(prompt, sizeof (prompt), - "vnts: h,l,{id},c{id},c {id}, q:"); + "vnts: h, l, c{id}, n{name}, q:"); } @@ -686,15 +712,31 @@ vntsd_console_thread(vntsd_thr_arg_t *argp) rv = VNTSD_STATUS_CLIENT_QUIT; break; - case 'h': - rv = display_help(clientp); + case ' ': + + if (clientp->cons == NULL) { + if (num_cons == 1) { + /* by pass selecting console */ + consp = (vntsd_cons_t *) + (groupp->conspq->handle); + } else { + continue; + } + + } else { + consp = clientp->cons; + } + + /* connect to console */ + rv = connect_cons(consp, clientp); + break; - default: + case 'c': + case 'n': /* select console */ if (clientp->cons == NULL) { - rv = select_cons(groupp, num_cons, - &consp, clientp, cmd); + rv = select_cons(groupp, &consp, clientp, cmd); if (rv == VNTSD_ERR_INVALID_INPUT) { rv = display_help(clientp); break; @@ -711,7 +753,13 @@ vntsd_console_thread(vntsd_thr_arg_t *argp) thr_self(), rv); break; + case 'h': + default: + rv = display_help(clientp); + break; + } + /* check error and may exit */ console_chk_status(groupp, clientp, rv); } diff --git a/usr/src/uts/sun4v/io/vdc.c b/usr/src/uts/sun4v/io/vdc.c index 0a77dd485a..6502c8394a 100644 --- a/usr/src/uts/sun4v/io/vdc.c +++ b/usr/src/uts/sun4v/io/vdc.c @@ -462,7 +462,7 @@ vdc_do_attach(dev_info_t *dip) vdc->ldc_state = 0; vdc->session_id = 0; vdc->block_size = DEV_BSIZE; - vdc->max_xfer_sz = VD_MAX_BLOCK_SIZE / DEV_BSIZE; + vdc->max_xfer_sz = maxphys / DEV_BSIZE; vdc->vtoc = NULL; vdc->cinfo = NULL; @@ -569,9 +569,6 @@ vdc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { int status; - PR0("%s[%d] Entered. Built %s %s\n", __func__, ddi_get_instance(dip), - __DATE__, __TIME__); - switch (cmd) { case DDI_ATTACH: if ((status = vdc_do_attach(dip)) != 0) @@ -2021,9 +2018,8 @@ vdc_populate_descriptor(vdc_t *vdc, caddr_t addr, size_t nbytes, int operation, int idx = 0; /* Index of DRing entry used */ vio_dring_msg_t dmsg; size_t msglen = sizeof (dmsg); - int status = 0; - int rv; int retries = 0; + int rv; ASSERT(vdc != NULL); ASSERT(slice < V_NUMPAR); @@ -2064,7 +2060,6 @@ vdc_populate_descriptor(vdc_t *vdc, caddr_t addr, size_t nbytes, int operation, rv = vdc_populate_mem_hdl(vdc, idx, addr, nbytes, operation); break; - case VD_OP_FLUSH: case VD_OP_GET_VTOC: case VD_OP_SET_VTOC: case VD_OP_GET_DISKGEOM: @@ -2075,6 +2070,13 @@ vdc_populate_descriptor(vdc_t *vdc, caddr_t addr, size_t nbytes, int operation, operation); } break; + + case VD_OP_FLUSH: + case VD_OP_GET_WCE: + case VD_OP_SET_WCE: + rv = 0; /* nothing to bind */ + break; + default: cmn_err(CE_NOTE, "[%d] Unsupported vDisk operation [%d]\n", vdc->instance, operation); @@ -2115,13 +2117,13 @@ vdc_populate_descriptor(vdc_t *vdc, caddr_t addr, size_t nbytes, int operation, dmsg.seq_num, dep->payload.req_id, dep); mutex_enter(&vdc->lock); - status = vdc_send(vdc, (caddr_t)&dmsg, &msglen); + rv = vdc_send(vdc, (caddr_t)&dmsg, &msglen); mutex_exit(&vdc->lock); - PR1("%s[%d]: ldc_write() status=%d\n", __func__, vdc->instance, status); - if (status != 0) { + PR1("%s[%d]: ldc_write() rv=%d\n", __func__, vdc->instance, rv); + if (rv != 0) { mutex_exit(&local_dep->lock); mutex_exit(&vdc->dring_lock); - vdc_msg("%s: ldc_write(%d)\n", __func__, status); + vdc_msg("%s: ldc_write(%d)\n", __func__, rv); return (EAGAIN); } @@ -2149,21 +2151,21 @@ vdc_populate_descriptor(vdc_t *vdc, caddr_t addr, size_t nbytes, int operation, retries = 0; for (;;) { msglen = sizeof (dmsg); - status = ldc_read(vdc->ldc_handle, (caddr_t)&dmsg, + rv = ldc_read(vdc->ldc_handle, (caddr_t)&dmsg, &msglen); - if (status) { - status = EINVAL; + if (rv) { + rv = EINVAL; break; } /* * if there are no packets wait and check again */ - if ((status == 0) && (msglen == 0)) { + if ((rv == 0) && (msglen == 0)) { if (retries++ > vdc_dump_retries) { PR0("[%d] Giving up waiting, idx %d\n", vdc->instance, idx); - status = EAGAIN; + rv = EAGAIN; break; } @@ -2191,10 +2193,10 @@ vdc_populate_descriptor(vdc_t *vdc, caddr_t addr, size_t nbytes, int operation, */ switch (dmsg.tag.vio_subtype) { case VIO_SUBTYPE_ACK: - status = 0; + rv = 0; break; case VIO_SUBTYPE_NACK: - status = EAGAIN; + rv = EAGAIN; break; default: continue; @@ -2238,26 +2240,26 @@ vdc_populate_descriptor(vdc_t *vdc, caddr_t addr, size_t nbytes, int operation, mutex_exit(&local_dep->lock); mutex_exit(&vdc->dring_lock); - return (status); + return (rv); } /* * Now watch the DRing entries we modified to get the response * from vds. */ - status = vdc_wait_for_descriptor_update(vdc, idx, dmsg); - if (status == ETIMEDOUT) { + rv = vdc_wait_for_descriptor_update(vdc, idx, dmsg); + if (rv == ETIMEDOUT) { /* debug info when dumping state on vds side */ dep->payload.status = ECANCELED; } - status = vdc_depopulate_descriptor(vdc, idx); - PR1("%s[%d] Status=%d\n", __func__, vdc->instance, status); + rv = vdc_depopulate_descriptor(vdc, idx); + PR1("%s[%d] Status=%d\n", __func__, vdc->instance, rv); mutex_exit(&local_dep->lock); mutex_exit(&vdc->dring_lock); - return (status); + return (rv); } /* @@ -2415,8 +2417,10 @@ static int vdc_depopulate_descriptor(vdc_t *vdc, uint_t idx) { vd_dring_entry_t *dep = NULL; /* Dring Entry Pointer */ - vdc_local_desc_t *ldep = NULL; /* Local Dring Entry Pointer */ - int status = ENXIO; + vdc_local_desc_t *ldep = NULL; /* Local Dring Entry Pointer */ + int status = ENXIO; + int operation; + int rv = 0; ASSERT(vdc != NULL); ASSERT(idx < VD_DRING_LEN); @@ -2426,10 +2430,17 @@ vdc_depopulate_descriptor(vdc_t *vdc, uint_t idx) ASSERT(dep != NULL); status = dep->payload.status; + operation = dep->payload.operation; VDC_MARK_DRING_ENTRY_FREE(vdc, idx); ldep = &vdc->local_dring[idx]; VIO_SET_DESC_STATE(ldep->flags, VIO_DESC_FREE); + /* the DKIO W$ operations never bind handles so we can return now */ + if ((operation == VD_OP_FLUSH) || + (operation == VD_OP_GET_WCE) || + (operation == VD_OP_SET_WCE)) + return (status); + /* * If the upper layer passed in a misaligned address we copied the * data into an aligned buffer before sending it to LDC - we now @@ -2445,10 +2456,17 @@ vdc_depopulate_descriptor(vdc_t *vdc, uint_t idx) ldep->align_addr = NULL; } - status = ldc_mem_unbind_handle(ldep->desc_mhdl); - if (status != 0) { + rv = ldc_mem_unbind_handle(ldep->desc_mhdl); + if (rv != 0) { cmn_err(CE_NOTE, "[%d] unbind mem hdl 0x%lx @ idx %d failed:%d", - vdc->instance, ldep->desc_mhdl, idx, status); + vdc->instance, ldep->desc_mhdl, idx, rv); + /* + * The error returned by the vDisk server is more informative + * and thus has a higher priority but if it isn't set we ensure + * that this function returns an error. + */ + if (status == 0) + status = EINVAL; } return (status); @@ -2498,7 +2516,6 @@ vdc_populate_mem_hdl(vdc_t *vdc, uint_t idx, caddr_t addr, size_t nbytes, perm = LDC_MEM_R; break; - case VD_OP_FLUSH: case VD_OP_GET_VTOC: case VD_OP_SET_VTOC: case VD_OP_GET_DISKGEOM: @@ -3477,10 +3494,9 @@ vdc_dkio_flush_cb(void *arg) rv = vdc_populate_descriptor(vdc, NULL, 0, VD_OP_FLUSH, dk_arg->mode, SDPART(getminor(dk_arg->dev))); if (rv != 0) { - PR0("%s[%d] DKIOCFLUSHWRITECACHE failed : model %x\n", - __func__, vdc->instance, + PR0("%s[%d] DKIOCFLUSHWRITECACHE failed %d : model %x\n", + __func__, vdc->instance, rv, ddi_model_convert_from(dk_arg->mode & FMODELS)); - return; } /* @@ -3491,7 +3507,7 @@ vdc_dkio_flush_cb(void *arg) (dkc != NULL) && (dkc->dkc_callback != NULL)) { ASSERT(dkc->dkc_cookie != NULL); - (*dkc->dkc_callback)(dkc->dkc_cookie, ENOTSUP); + (*dkc->dkc_callback)(dkc->dkc_cookie, rv); } /* Indicate that one less DKIO write flush is outstanding */ @@ -3499,6 +3515,9 @@ vdc_dkio_flush_cb(void *arg) vdc->dkio_flush_pending--; ASSERT(vdc->dkio_flush_pending >= 0); mutex_exit(&vdc->lock); + + /* free the mem that was allocated when the callback was dispatched */ + kmem_free(arg, sizeof (vdc_dk_arg_t)); } /* @@ -3647,15 +3666,67 @@ vd_process_ioctl(dev_t dev, int cmd, caddr_t arg, int mode) } case DKIOCGMEDIAINFO: - if (vdc->minfo == NULL) - return (ENXIO); + { + if (vdc->minfo == NULL) + return (ENXIO); - rv = ddi_copyout(vdc->minfo, (void *)arg, - sizeof (struct dk_minfo), mode); - if (rv != 0) - return (EFAULT); + rv = ddi_copyout(vdc->minfo, (void *)arg, + sizeof (struct dk_minfo), mode); + if (rv != 0) + return (EFAULT); - return (0); + return (0); + } + + case DKIOCFLUSHWRITECACHE: + { + struct dk_callback *dkc = (struct dk_callback *)arg; + vdc_dk_arg_t *dkarg = NULL; + + PR1("[%d] Flush W$: mode %x\n", instance, mode); + + /* + * If the backing device is not a 'real' disk then the + * W$ operation request to the vDisk server will fail + * so we might as well save the cycles and return now. + */ + if (vdc->vdisk_type != VD_DISK_TYPE_DISK) + return (ENOTTY); + + /* + * If arg is NULL, then there is no callback function + * registered and the call operates synchronously; we + * break and continue with the rest of the function and + * wait for vds to return (i.e. after the request to + * vds returns successfully, all writes completed prior + * to the ioctl will have been flushed from the disk + * write cache to persistent media. + * + * If a callback function is registered, we dispatch + * the request on a task queue and return immediately. + * The callback will deal with informing the calling + * thread that the flush request is completed. + */ + if (dkc == NULL) + break; + + dkarg = kmem_zalloc(sizeof (vdc_dk_arg_t), KM_SLEEP); + + dkarg->mode = mode; + dkarg->dev = dev; + bcopy(dkc, &dkarg->dkc, sizeof (*dkc)); + + mutex_enter(&vdc->lock); + vdc->dkio_flush_pending++; + dkarg->vdc = vdc; + mutex_exit(&vdc->lock); + + /* put the request on a task queue */ + rv = taskq_dispatch(system_taskq, vdc_dkio_flush_cb, + (void *)dkarg, DDI_SLEEP); + + return (rv == NULL ? ENOMEM : 0); + } } /* catch programming error in vdc - should be a VD_OP_XXX ioctl */ @@ -3685,44 +3756,6 @@ vd_process_ioctl(dev_t dev, int cmd, caddr_t arg, int mode) } /* - * handle the special case of DKIOCFLUSHWRITECACHE - */ - if (cmd == DKIOCFLUSHWRITECACHE) { - struct dk_callback *dkc = (struct dk_callback *)arg; - - PR0("%s[%d]: DKIOCFLUSHWRITECACHE\n", __func__, instance); - - /* no mem should have been allocated hence no need to free it */ - ASSERT(mem_p == NULL); - - /* - * If arg is NULL, we break here and the call operates - * synchronously; waiting for vds to return. - * - * i.e. after the request to vds returns successfully, - * all writes completed prior to the ioctl will have been - * flushed from the disk write cache to persistent media. - */ - if (dkc != NULL) { - vdc_dk_arg_t arg; - arg.mode = mode; - arg.dev = dev; - bcopy(dkc, &arg.dkc, sizeof (*dkc)); - - mutex_enter(&vdc->lock); - vdc->dkio_flush_pending++; - arg.vdc = vdc; - mutex_exit(&vdc->lock); - - /* put the request on a task queue */ - rv = taskq_dispatch(system_taskq, vdc_dkio_flush_cb, - (void *)&arg, DDI_SLEEP); - - return (rv == NULL ? ENOMEM : 0); - } - } - - /* * send request to vds to service the ioctl. */ rv = vdc_populate_descriptor(vdc, mem_p, alloc_len, dk_ioctl[idx].op, @@ -4024,7 +4057,8 @@ vdc_create_fake_geometry(vdc_t *vdc) (void) strcpy(vdc->cinfo->dki_cname, VDC_DRIVER_NAME); (void) strcpy(vdc->cinfo->dki_dname, VDC_DRIVER_NAME); - vdc->cinfo->dki_maxtransfer = vdc->max_xfer_sz / vdc->block_size; + /* max_xfer_sz is #blocks so we don't need to divide by DEV_BSIZE */ + vdc->cinfo->dki_maxtransfer = vdc->max_xfer_sz; vdc->cinfo->dki_ctype = DKC_SCSI_CCS; vdc->cinfo->dki_flags = DKI_FMTVOL; vdc->cinfo->dki_cnum = 0; diff --git a/usr/src/uts/sun4v/io/vds.c b/usr/src/uts/sun4v/io/vds.c index 02f1c90ca4..adcea0c944 100644 --- a/usr/src/uts/sun4v/io/vds.c +++ b/usr/src/uts/sun4v/io/vds.c @@ -2251,8 +2251,6 @@ _init(void) { int i, status; - - PR0("Built %s %s", __DATE__, __TIME__); if ((status = ddi_soft_state_init(&vds_state, sizeof (vds_t), 1)) != 0) return (status); if ((status = mod_install(&modlinkage)) != 0) { @@ -2278,8 +2276,6 @@ _fini(void) { int status; - - PR0("Entered"); if ((status = mod_remove(&modlinkage)) != 0) return (status); ddi_soft_state_fini(&vds_state); diff --git a/usr/src/uts/sun4v/io/vnet.c b/usr/src/uts/sun4v/io/vnet.c index ad625953e7..96bfb613f6 100644 --- a/usr/src/uts/sun4v/io/vnet.c +++ b/usr/src/uts/sun4v/io/vnet.c @@ -122,7 +122,7 @@ static struct ether_addr etherbroadcastaddr = { /* * This is the string displayed by modinfo(1m). */ -static char vnet_ident[] = "vnet driver v1.0"; +static char vnet_ident[] = "vnet driver v%I%"; extern struct mod_ops mod_driverops; static struct cb_ops cb_vnetops = { nulldev, /* cb_open */ @@ -545,12 +545,9 @@ vnet_m_unicst(void *arg, const uint8_t *macaddr) /* * XXX: setting mac address dynamically is not supported. */ -#if 0 - bcopy(macaddr, vnetp->curr_macaddr, ETHERADDRL); -#endif DBG1((vnetp, "vnet_m_unicst: exit\n")); - return (VNET_SUCCESS); + return (VNET_FAILURE); } /* enable/disable a multicast address */ diff --git a/usr/src/uts/sun4v/io/vnet_gen.c b/usr/src/uts/sun4v/io/vnet_gen.c index 56f753e5e7..e93f064eee 100644 --- a/usr/src/uts/sun4v/io/vnet_gen.c +++ b/usr/src/uts/sun4v/io/vnet_gen.c @@ -252,8 +252,8 @@ static vgen_ver_t vgen_versions[VGEN_NUM_VER] = { {1, 0} }; /* Tunables */ uint32_t vgen_hwd_interval = 1000; /* handshake watchdog freq in msec */ uint32_t vgen_max_hretries = 1; /* max # of handshake retries */ - uint32_t vgen_ldcwr_retries = 10; /* max # of ldc_write() retries */ +uint32_t vgen_ldcup_retries = 5; /* max # of ldc_up() retries */ #ifdef DEBUG /* flags to simulate error conditions for debugging */ @@ -553,17 +553,11 @@ vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp) { void *vnetp; size_t size; - uint64_t datalen; - uchar_t *rptr; - mblk_t *bp = NULL; int rv; uint32_t i; uint32_t start; uint32_t end; int txpending = 0; - int ci; - uint32_t ncookies; - uint64_t nc; vgen_private_desc_t *tbufp; vgen_private_desc_t *ntbufp; vnet_public_desc_t *txdp; @@ -574,65 +568,36 @@ vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp) boolean_t is_mcast = B_FALSE; boolean_t reclaim = B_FALSE; boolean_t need_intr = B_FALSE; - boolean_t err = B_FALSE; vnetp = LDC_TO_VNET(ldcp); statsp = ldcp->statsp; + size = msgsize(mp); + DBG1((vnetp, "vgen_ldcsend: enter ldcid(%lx)\n", ldcp->ldc_id)); - /* drop the packet if handshake is not done or ldc is not up */ - if ((ldcp->hphase != VH_DONE) || (ldcp->ldc_status != LDC_UP)) { + mutex_enter(&ldcp->txlock); + + /* drop the packet if ldc is not up or handshake is not done */ + if (ldcp->ldc_status != LDC_UP) { DWARN((vnetp, "vgen_ldcsend: id(%lx) status(%d), dropping packet\n", ldcp->ldc_id, ldcp->ldc_status)); - freemsg(mp); - return (VGEN_TX_SUCCESS); + /* retry ldc_up() if needed */ + if (ldcp->flags & CHANNEL_STARTED) + (void) ldc_up(ldcp->ldc_handle); + goto vgen_tx_exit; + } + + if (ldcp->hphase != VH_DONE) { + DWARN((vnetp, + "vgen_ldcsend: id(%lx) hphase(%x), dropping packet\n", + ldcp->ldc_id, ldcp->hphase)); + goto vgen_tx_exit; } - size = msgsize(mp); if (size > (size_t)ETHERMAX) { DWARN((vnetp, "vgen_ldcsend: id(%lx) invalid size(%d)\n", ldcp->ldc_id, size)); - freemsg(mp); - return (VGEN_TX_SUCCESS); - } - if ((size < (size_t)ETHERMIN) || /* needs padding to ETHERMIN */ - (mp->b_cont) || /* more than 1 mblk */ - ((uintptr_t)mp->b_rptr & 0x7) || /* data not 8 byte aligned */ - ((mp->b_wptr - mp->b_rptr) & 0x7)) { /* datalen not multiple of 8 */ - if (size < ETHERMIN) - size = ETHERMIN; - /* - * The data buffer returned by allocb(9F) is 8byte aligned. - * We allocate extra 8 bytes to ensure size is multiple of - * 8 bytes for ldc_mem_bind_handle(). - */ - bp = allocb(size + 8, BPRI_MED); - if (bp == NULL) { - /* drop the packet */ - freemsg(mp); - mutex_enter(&ldcp->txlock); - statsp->tx_allocb_fail++; - mutex_exit(&ldcp->txlock); - return (VGEN_TX_SUCCESS); - } - vgen_copymsg(mp, bp->b_rptr); - bp->b_wptr += size; - datalen = size; /* actual data length without pad */ - size = (datalen + 7) & ~7; - bp->b_wptr += (size - datalen); - } else { /* size/alignment are ok */ - datalen = size; - } - - mutex_enter(&ldcp->txlock); - - /* check if the channel is still up & running */ - if ((ldcp->hphase != VH_DONE) || (ldcp->ldc_status != LDC_UP)) { - DWARN((vnetp, - "vgen_ldcsend: id(%lx) status(%d), dropping packet\n", - ldcp->ldc_id, ldcp->ldc_status)); - err = B_TRUE; goto vgen_tx_exit; } @@ -651,8 +616,6 @@ vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp) statsp->tx_no_desc++; mutex_exit(&ldcp->txlock); - if (bp) - freemsg(bp); #ifdef VGEN_USE_MAC_TX_UPDATE /* * This cflag is disabled by default. This can be enabled if we @@ -672,6 +635,12 @@ vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp) #endif } + if (size < ETHERMIN) + size = ETHERMIN; + + /* copy data into pre-allocated transmit buffer */ + vgen_copymsg(mp, tbufp->datap); + txpending = vgen_num_txpending(ldcp); if (txpending >= ldcp->reclaim_hiwat) { /* @@ -692,55 +661,12 @@ vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp) i = tbufp - ldcp->tbufp; - rptr = bp ? (bp->b_rptr) : (mp->b_rptr); - ci = 0; - rv = ldc_mem_bind_handle(tbufp->memhandle, (caddr_t)rptr, size, - LDC_SHADOW_MAP, LDC_MEM_R, &(tbufp->memcookie[ci]), &ncookies); - if (rv != 0) { - DWARN((vnetp, "vgen_ldcsend: id(%lx)ldc_mem_bind_handle failed" - " rv(%d) tbufi(%d)\n", ldcp->ldc_id, rv, i)); - err = B_TRUE; - statsp->oerrors++; - goto vgen_tx_exit; - } - - if ((ncookies < 0) || (ncookies > (uint64_t)MAX_COOKIES)) { - DWARN((vnetp, - "vgen_ldcsend: id(%lx)ldc_mem_bind_handle returned" - " invalid cookies (%d)\n", ldcp->ldc_id, ncookies)); - err = B_TRUE; - statsp->oerrors++; - (void) ldc_mem_unbind_handle(tbufp->memhandle); - goto vgen_tx_exit; - } - - if (ncookies > 1) { - nc = ncookies - 1; - while (nc) { - ci++; - rv = ldc_mem_nextcookie(tbufp->memhandle, - &(tbufp->memcookie[ci])); - if (rv != 0) { - DWARN((vnetp, - "vgen_ldcsend: ldc_mem_nextcookie" - " err(%d)\n", rv)); - err = B_TRUE; - statsp->oerrors++; - (void) ldc_mem_unbind_handle(tbufp->memhandle); - goto vgen_tx_exit; - } - nc--; - } - } - - ehp = (struct ether_header *)rptr; + ehp = (struct ether_header *)tbufp->datap; is_bcast = IS_BROADCAST(ehp); is_mcast = IS_MULTICAST(ehp); - /* save the packet, free when the descr done flag is set */ - tbufp->mp = (bp ? bp : mp); + tbufp->flags = VGEN_PRIV_DESC_BUSY; - tbufp->datalen = datalen; - tbufp->ncookies = ncookies; + tbufp->datalen = size; tbufp->seqnum = ldcp->next_txseq; /* initialize the corresponding public descriptor (txd) */ @@ -749,10 +675,10 @@ vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp) hdrp->dstate = VIO_DESC_READY; if (need_intr) hdrp->ack = B_TRUE; - txdp->nbytes = datalen; - txdp->ncookies = ncookies; + txdp->nbytes = size; + txdp->ncookies = tbufp->ncookies; bcopy((tbufp->memcookie), (txdp->memcookie), - ncookies * sizeof (ldc_mem_cookie_t)); + tbufp->ncookies * sizeof (ldc_mem_cookie_t)); /* send dring datamsg to the peer */ start = end = i; @@ -761,13 +687,11 @@ vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp) /* vgen_send_dring_data() error: drop the packet */ DWARN((vnetp, "vgen_ldcsend: vgen_send_dring_data(): failed: " - "id(%lx) rv(%d) len (%d)\n", ldcp->ldc_id, rv, datalen)); - (void) ldc_mem_unbind_handle(tbufp->memhandle); + "id(%lx) rv(%d) len (%d)\n", ldcp->ldc_id, rv, size)); tbufp->flags = VGEN_PRIV_DESC_FREE; /* free tbuf */ hdrp->dstate = VIO_DESC_FREE; /* free txd */ hdrp->ack = B_FALSE; statsp->oerrors++; - err = B_TRUE; goto vgen_tx_exit; } @@ -779,7 +703,7 @@ vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp) /* update stats */ statsp->opackets++; - statsp->obytes += datalen; + statsp->obytes += size; if (is_bcast) statsp->brdcstxmt++; else if (is_mcast) @@ -793,20 +717,8 @@ vgen_tx_exit: } DBG1((vnetp, "vgen_ldcsend: exit: ldcid (%lx)\n", ldcp->ldc_id)); - if (err) { - if (bp) - freemsg(bp); -#ifdef VGEN_USE_MAC_TX_UPDATE - return (VGEN_TX_FAILURE); /* transmit failed */ -#else - freemsg(mp); /* drop the packet */ - return (VGEN_TX_SUCCESS); -#endif - } else { - if (bp) /* free original pkt, copy is in bp */ - freemsg(mp); - return (VGEN_TX_SUCCESS); - } + freemsg(mp); + return (VGEN_TX_SUCCESS); } /* register resources */ @@ -1869,6 +1781,7 @@ vgen_ldc_init(vgen_ldc_t *ldcp) } init_state; uint32_t ncookies = 0; + uint32_t retries = 0; init_state = ST_init; @@ -1915,12 +1828,17 @@ vgen_ldc_init(vgen_ldc_t *ldcp) init_state |= ST_dring_bind; - rv = ldc_up(ldcp->ldc_handle); - if (rv != 0) { - DBG2((vnetp, - "vgen_ldcinit: ldc_up err id(%lx) rv(%d)\n", - ldcp->ldc_id, rv)); - } + do { + rv = ldc_up(ldcp->ldc_handle); + if ((rv != 0) && (rv == EWOULDBLOCK)) { + DBG2((vnetp, + "vgen_ldcinit: ldc_up err id(%lx) rv(%d)\n", + ldcp->ldc_id, rv)); + drv_usecwait(VGEN_LDC_UP_DELAY); + } + if (retries++ >= vgen_ldcup_retries) + break; + } while (rv == EWOULDBLOCK); (void) ldc_status(ldcp->ldc_handle, &istatus); if (istatus != LDC_UP) { @@ -2021,17 +1939,24 @@ vgen_init_tbufs(vgen_ldc_t *ldcp) vio_dring_entry_hdr_t *hdrp; int i; int rv; + caddr_t datap = NULL; + int ci; + uint32_t ncookies; bzero(ldcp->tbufp, sizeof (*tbufp) * (ldcp->num_txds)); bzero(ldcp->txdp, sizeof (*txdp) * (ldcp->num_txds)); + datap = kmem_zalloc(ldcp->num_txds * VGEN_TX_DBLK_SZ, KM_SLEEP); + ldcp->tx_datap = datap; + /* - * for each tx buf (priv_desc), allocate a ldc mem_handle which is + * for each private descriptor, allocate a ldc mem_handle which is * required to map the data during transmit, set the flags * to free (available for use by transmit routine). */ for (i = 0; i < ldcp->num_txds; i++) { + tbufp = &(ldcp->tbufp[i]); rv = ldc_mem_alloc_handle(ldcp->ldc_handle, &(tbufp->memhandle)); @@ -2039,12 +1964,47 @@ vgen_init_tbufs(vgen_ldc_t *ldcp) tbufp->memhandle = 0; goto init_tbufs_failed; } + + /* + * bind ldc memhandle to the corresponding transmit buffer. + */ + ci = ncookies = 0; + rv = ldc_mem_bind_handle(tbufp->memhandle, + (caddr_t)datap, VGEN_TX_DBLK_SZ, LDC_SHADOW_MAP, + LDC_MEM_R, &(tbufp->memcookie[ci]), &ncookies); + if (rv != 0) { + goto init_tbufs_failed; + } + + /* + * successful in binding the handle to tx data buffer. + * set datap in the private descr to this buffer. + */ + tbufp->datap = datap; + + if ((ncookies == 0) || + (ncookies > (uint64_t)MAX_COOKIES)) { + goto init_tbufs_failed; + } + + for (ci = 1; ci < ncookies; ci++) { + rv = ldc_mem_nextcookie(tbufp->memhandle, + &(tbufp->memcookie[ci])); + if (rv != 0) { + goto init_tbufs_failed; + } + } + + tbufp->ncookies = ncookies; + datap += VGEN_TX_DBLK_SZ; + tbufp->flags = VGEN_PRIV_DESC_FREE; txdp = &(ldcp->txdp[i]); hdrp = &txdp->hdr; hdrp->dstate = VIO_DESC_FREE; hdrp->ack = B_FALSE; tbufp->descp = txdp; + } /* reset tbuf walking pointers */ @@ -2078,14 +2038,13 @@ vgen_uninit_tbufs(vgen_ldc_t *ldcp) txdp = tbufp->descp; hdrp = &txdp->hdr; - if (tbufp->flags != VGEN_PRIV_DESC_FREE) { + if (tbufp->datap) { /* if bound to a ldc memhandle */ (void) ldc_mem_unbind_handle(tbufp->memhandle); - freemsg(tbufp->mp); - tbufp->mp = NULL; - tbufp->flags = VGEN_PRIV_DESC_FREE; - hdrp->dstate = VIO_DESC_FREE; - hdrp->ack = B_FALSE; + tbufp->datap = NULL; } + tbufp->flags = VGEN_PRIV_DESC_FREE; + hdrp->dstate = VIO_DESC_FREE; + hdrp->ack = B_FALSE; if (tbufp->memhandle) { (void) ldc_mem_free_handle(tbufp->memhandle); tbufp->memhandle = 0; @@ -2093,6 +2052,12 @@ vgen_uninit_tbufs(vgen_ldc_t *ldcp) tbufp->descp = NULL; } + if (ldcp->tx_datap) { + /* prealloc'd tx data buffer */ + kmem_free(ldcp->tx_datap, ldcp->num_txds * VGEN_TX_DBLK_SZ); + ldcp->tx_datap = NULL; + } + bzero(ldcp->tbufp, sizeof (*tbufp) * (ldcp->num_txds)); bzero(ldcp->txdp, sizeof (*txdp) * (ldcp->num_txds)); } @@ -2117,9 +2082,6 @@ vgen_clobber_tbufs(vgen_ldc_t *ldcp) hdrp = &txdp->hdr; if (tbufp->flags & VGEN_PRIV_DESC_BUSY) { - (void) ldc_mem_unbind_handle(tbufp->memhandle); - freemsg(tbufp->mp); - tbufp->mp = NULL; tbufp->flags = VGEN_PRIV_DESC_FREE; #ifdef DEBUG if (hdrp->dstate == VIO_DESC_DONE) @@ -4344,8 +4306,6 @@ vgen_next_rxi: if (rxi == end) { tbufp = &(ldcp->tbufp[txi]); txdp = tbufp->descp; hdrp = &txdp->hdr; - (void) ldc_mem_unbind_handle(tbufp->memhandle); - freemsg(tbufp->mp); tbufp->flags = VGEN_PRIV_DESC_FREE; hdrp->dstate = VIO_DESC_FREE; hdrp->ack = B_FALSE; @@ -4419,9 +4379,6 @@ vgen_reclaim_dring(vgen_ldc_t *ldcp) while ((hdrp->dstate == VIO_DESC_DONE) && (tbufp != ldcp->next_tbufp)) { - (void) ldc_mem_unbind_handle(tbufp->memhandle); - freemsg(tbufp->mp); - tbufp->mp = NULL; tbufp->flags = VGEN_PRIV_DESC_FREE; hdrp->dstate = VIO_DESC_FREE; hdrp->ack = B_FALSE; diff --git a/usr/src/uts/sun4v/os/hsvc.c b/usr/src/uts/sun4v/os/hsvc.c index e06012e920..1b2e0e5b6e 100644 --- a/usr/src/uts/sun4v/os/hsvc.c +++ b/usr/src/uts/sun4v/os/hsvc.c @@ -654,15 +654,12 @@ hsvc_init(void) * uses hypervisor services belonging to the HSVC_GROUP_CORE API * group only for itself. * - * Rest of the API groups are currently negotiated on behalf - * of the pcitool, glvc support. In future, when these drivers - * are modified to do the negotiation themselves, corresponding - * entry should be removed from the table below. + * Note that the HSVC_GROUP_DIAG is negotiated on behalf of + * any driver/module using DIAG services. */ static hsvc_info_t hsvcinfo_unix[] = { {HSVC_REV_1, NULL, HSVC_GROUP_SUN4V, 1, 0, NULL}, {HSVC_REV_1, NULL, HSVC_GROUP_CORE, 1, 1, NULL}, - {HSVC_REV_1, NULL, HSVC_GROUP_VSC, 1, 0, NULL}, {HSVC_REV_1, NULL, HSVC_GROUP_DIAG, 1, 0, NULL} }; diff --git a/usr/src/uts/sun4v/sys/vnet_gen.h b/usr/src/uts/sun4v/sys/vnet_gen.h index 2ce1f390d8..77a088fcb0 100644 --- a/usr/src/uts/sun4v/sys/vnet_gen.h +++ b/usr/src/uts/sun4v/sys/vnet_gen.h @@ -69,6 +69,9 @@ extern "C" { #define LDC_TO_VNET(ldcp) ((ldcp)->portp->vgenp->vnetp) #define LDC_TO_VGEN(ldcp) ((ldcp)->portp->vgenp) +#define VGEN_TX_DBLK_SZ 2048 /* tx data buffer size */ +#define VGEN_LDC_UP_DELAY 100 /* usec delay between ldc_up retries */ + /* get the address of next tbuf */ #define NEXTTBUF(ldcp, tbufp) (((tbufp) + 1) == (ldcp)->tbufendp \ ? (ldcp)->tbufp : ((tbufp) + 1)) @@ -102,8 +105,7 @@ typedef struct vgen_priv_desc { uint64_t flags; /* flag bits */ vnet_public_desc_t *descp; /* associated public desc */ ldc_mem_handle_t memhandle; /* mem handle for data */ - mblk_t *mp; /* associated packet */ - uint64_t datap; /* mp->b_rptr */ + caddr_t datap; /* prealloc'd tx data buffer */ uint64_t datalen; /* total actual datalen */ uint64_t seqnum; /* sequence number of pkt */ uint64_t ncookies; /* num ldc_mem_cookies */ @@ -274,6 +276,7 @@ typedef struct vgen_ldc { uint64_t next_rxseq; /* next expected recv seqnum */ uint32_t next_rxi; /* next expected recv index */ uint32_t num_rxds; /* number of rx descriptors */ + caddr_t tx_datap; /* prealloc'd tx data area */ /* misc */ uint32_t flags; /* flags */ |
