summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorlm66018 <none@none>2006-06-02 07:47:46 -0700
committerlm66018 <none@none>2006-06-02 07:47:46 -0700
commit8e6a2a040587479821d1e682a28bcef7e75f19a6 (patch)
tree6b09b06afed1b71c8d225dc76d30e3ad22c10040 /usr/src
parent297a2ad14ba0591f210adbe7bb5c9f70af7fe56a (diff)
downloadillumos-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.c24
-rw-r--r--usr/src/cmd/vntsd/console.c126
-rw-r--r--usr/src/uts/sun4v/io/vdc.c194
-rw-r--r--usr/src/uts/sun4v/io/vds.c4
-rw-r--r--usr/src/uts/sun4v/io/vnet.c7
-rw-r--r--usr/src/uts/sun4v/io/vnet_gen.c243
-rw-r--r--usr/src/uts/sun4v/os/hsvc.c7
-rw-r--r--usr/src/uts/sun4v/sys/vnet_gen.h7
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 */