summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/boot/usb/bsd_kernel.h3
-rw-r--r--sys/cam/ata/ata_da.c8
-rw-r--r--sys/cam/ctl/ctl.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c8
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c51
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c40
-rw-r--r--sys/dev/ata/ata-all.c30
-rw-r--r--sys/dev/ata/ata-all.h9
-rw-r--r--sys/dev/ciss/ciss.c8
-rw-r--r--sys/dev/filemon/filemon.c27
-rw-r--r--sys/dev/filemon/filemon_lock.c77
-rw-r--r--sys/dev/filemon/filemon_wrapper.c150
-rw-r--r--sys/dev/ipmi/ipmi.c23
-rw-r--r--sys/dev/ipmi/ipmi_kcs.c1
-rw-r--r--sys/dev/ipmi/ipmi_smic.c1
-rw-r--r--sys/dev/ipmi/ipmivars.h1
-rw-r--r--sys/dev/isci/isci.c2
-rw-r--r--sys/dev/isci/isci_interrupt.c4
-rw-r--r--sys/dev/ixgbe/if_ix.c6
-rw-r--r--sys/dev/md/md.c9
-rw-r--r--sys/dev/nvme/nvme.c9
-rw-r--r--sys/dev/sound/midi/midi.c2
-rw-r--r--sys/dev/usb/controller/dwc_otg.c762
-rw-r--r--sys/dev/usb/controller/dwc_otg.h18
-rw-r--r--sys/dev/usb/controller/dwc_otgreg.h2
-rw-r--r--sys/dev/usb/controller/usb_controller.c14
-rw-r--r--sys/dev/usb/serial/u3g.c2
-rw-r--r--sys/dev/usb/usb_bus.h19
-rw-r--r--sys/dev/usb/usb_device.c2
-rw-r--r--sys/dev/usb/usb_hub.c4
-rw-r--r--sys/dev/usb/usb_pf.c6
-rw-r--r--sys/dev/usb/usb_process.h1
-rw-r--r--sys/dev/usb/usb_transfer.c63
-rw-r--r--sys/dev/usb/usbdevs3
-rw-r--r--sys/dev/usb/usbdi.h2
-rw-r--r--sys/fs/nfsserver/nfs_nfsdstate.c7
-rw-r--r--sys/fs/procfs/procfs_ctl.c2
-rw-r--r--sys/geom/geom_io.c48
-rw-r--r--sys/gnu/fs/reiserfs/reiserfs_vfsops.c4
-rw-r--r--sys/kern/init_main.c4
-rw-r--r--sys/kern/kern_exit.c33
-rw-r--r--sys/kern/kern_timeout.c2
-rw-r--r--sys/kern/ksched.c164
-rw-r--r--sys/kern/subr_witness.c2
-rw-r--r--sys/kern/sys_process.c11
-rw-r--r--sys/net/if_epair.c52
-rw-r--r--sys/netpfil/pf/pf.c12
-rw-r--r--sys/ofed/include/linux/in.h4
-rw-r--r--sys/ofed/include/linux/linux_compat.c45
-rw-r--r--sys/ofed/include/linux/mm.h2
-rw-r--r--sys/rpc/rpc_generic.c4
-rw-r--r--sys/rpc/svc_vc.c6
-rw-r--r--sys/sys/posix4.h3
-rw-r--r--sys/sys/socketvar.h2
-rw-r--r--sys/x86/include/specialreg.h1
-rw-r--r--sys/x86/x86/identcpu.c2
57 files changed, 852 insertions, 929 deletions
diff --git a/sys/boot/usb/bsd_kernel.h b/sys/boot/usb/bsd_kernel.h
index cb947dd..74bccd6 100644
--- a/sys/boot/usb/bsd_kernel.h
+++ b/sys/boot/usb/bsd_kernel.h
@@ -42,7 +42,8 @@
#define M_USBDEV 0
#define USB_PROC_MAX 3
#define USB_BUS_GIANT_PROC(bus) (usb_process + 2)
-#define USB_BUS_NON_GIANT_PROC(bus) (usb_process + 2)
+#define USB_BUS_NON_GIANT_BULK_PROC(bus) (usb_process + 2)
+#define USB_BUS_NON_GIANT_ISOC_PROC(bus) (usb_process + 2)
#define USB_BUS_EXPLORE_PROC(bus) (usb_process + 0)
#define USB_BUS_CONTROL_XFER_PROC(bus) (usb_process + 1)
#define SYSCTL_DECL(...)
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index 925dba9..ed8eb4d 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -1535,9 +1535,7 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
} else {
/* This can happen if DMA was disabled. */
bioq_remove(&softc->trim_queue, bp);
- bp->bio_error = EOPNOTSUPP;
- bp->bio_flags |= BIO_ERROR;
- biodone(bp);
+ biofinish(bp, NULL, EOPNOTSUPP);
xpt_release_ccb(start_ccb);
adaschedule(periph);
return;
@@ -1602,9 +1600,7 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
}
}
if (fail) {
- bp->bio_error = EIO;
- bp->bio_flags |= BIO_ERROR;
- biodone(bp);
+ biofinish(bp, NULL, EIO);
xpt_release_ccb(start_ccb);
adaschedule(periph);
return;
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 8f3dd95..e07e2d0 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -9473,7 +9473,7 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
*/
if (request_lun != NULL) {
mtx_lock(&lun->lun_lock);
- ctl_clr_ua(lun, initidx, CTL_UA_RES_RELEASE);
+ ctl_clr_ua(lun, initidx, CTL_UA_LUN_CHANGE);
mtx_unlock(&lun->lun_lock);
}
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
index 0a38cff..1955984 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
@@ -3510,7 +3510,6 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
*/
if (DTRACE_ANCHORED(mstate->dtms_probe) && CPU_ON_INTR(CPU))
return ((uint64_t)p0.p_cred->cr_uid);
-#endif
/*
* It is always safe to dereference one's own t_procp pointer:
@@ -3522,6 +3521,9 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
* credential, since this is never NULL after process birth.
*/
return ((uint64_t)curthread->t_procp->p_cred->cr_uid);
+#else
+ return ((uint64_t)curthread->td_ucred->cr_uid);
+#endif
case DIF_VAR_GID:
if (!dtrace_priv_proc(state))
@@ -3533,7 +3535,6 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
*/
if (DTRACE_ANCHORED(mstate->dtms_probe) && CPU_ON_INTR(CPU))
return ((uint64_t)p0.p_cred->cr_gid);
-#endif
/*
* It is always safe to dereference one's own t_procp pointer:
@@ -3545,6 +3546,9 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
* credential, since this is never NULL after process birth.
*/
return ((uint64_t)curthread->t_procp->p_cred->cr_gid);
+#else
+ return ((uint64_t)curthread->td_ucred->cr_gid);
+#endif
case DIF_VAR_ERRNO: {
#if defined(sun)
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
index 85defb0..30aac16 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
@@ -1823,7 +1823,7 @@ arc_hdr_destroy(arc_buf_hdr_t *hdr)
if (l2hdr != NULL) {
trim_map_free(l2hdr->b_dev->l2ad_vdev, l2hdr->b_daddr,
- hdr->b_size, 0);
+ l2hdr->b_asize, 0);
list_remove(l2hdr->b_dev->l2ad_buflist, hdr);
arc_buf_l2_cdata_free(hdr);
ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size);
@@ -3822,7 +3822,7 @@ arc_release(arc_buf_t *buf, void *tag)
vdev_space_update(l2hdr->b_dev->l2ad_vdev,
-l2hdr->b_asize, 0, 0);
trim_map_free(l2hdr->b_dev->l2ad_vdev, l2hdr->b_daddr,
- hdr->b_size, 0);
+ l2hdr->b_asize, 0);
kmem_free(l2hdr, sizeof (l2arc_buf_hdr_t));
ARCSTAT_INCR(arcstat_l2_size, -buf_size);
mutex_exit(&l2arc_buflist_mtx);
@@ -4761,7 +4761,7 @@ l2arc_write_done(zio_t *zio)
bytes_dropped += abl2->b_asize;
hdr->b_l2hdr = NULL;
trim_map_free(abl2->b_dev->l2ad_vdev, abl2->b_daddr,
- hdr->b_size, 0);
+ abl2->b_asize, 0);
kmem_free(abl2, sizeof (l2arc_buf_hdr_t));
ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size);
}
@@ -5062,8 +5062,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
{
arc_buf_hdr_t *hdr, *hdr_prev, *head;
list_t *list;
- uint64_t write_asize, write_psize, write_sz, headroom,
- buf_compress_minsz;
+ uint64_t write_asize, write_sz, headroom, buf_compress_minsz;
void *buf_data;
kmutex_t *list_lock;
boolean_t full;
@@ -5079,7 +5078,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
*headroom_boost = B_FALSE;
pio = NULL;
- write_sz = write_asize = write_psize = 0;
+ write_sz = write_asize = 0;
full = B_FALSE;
head = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE);
head->b_flags |= ARC_FLAG_L2_WRITE_HEAD;
@@ -5122,6 +5121,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
l2arc_buf_hdr_t *l2hdr;
kmutex_t *hash_lock;
uint64_t buf_sz;
+ uint64_t buf_a_sz;
if (arc_warm == B_FALSE)
hdr_prev = list_next(list, hdr);
@@ -5153,7 +5153,15 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
continue;
}
- if ((write_sz + hdr->b_size) > target_sz) {
+ /*
+ * Assume that the buffer is not going to be compressed
+ * and could take more space on disk because of a larger
+ * disk block size.
+ */
+ buf_sz = hdr->b_size;
+ buf_a_sz = vdev_psize_to_asize(dev->l2ad_vdev, buf_sz);
+
+ if ((write_asize + buf_a_sz) > target_sz) {
full = B_TRUE;
mutex_exit(hash_lock);
ARCSTAT_BUMP(arcstat_l2_write_full);
@@ -5196,7 +5204,6 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
l2hdr->b_asize = hdr->b_size;
l2hdr->b_tmp_cdata = hdr->b_buf->b_data;
- buf_sz = hdr->b_size;
hdr->b_l2hdr = l2hdr;
list_insert_head(dev->l2ad_buflist, hdr);
@@ -5211,6 +5218,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
mutex_exit(hash_lock);
write_sz += buf_sz;
+ write_asize += buf_a_sz;
}
mutex_exit(list_lock);
@@ -5228,6 +5236,19 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
}
/*
+ * Note that elsewhere in this file arcstat_l2_asize
+ * and the used space on l2ad_vdev are updated using b_asize,
+ * which is not necessarily rounded up to the device block size.
+ * Too keep accounting consistent we do the same here as well:
+ * stats_size accumulates the sum of b_asize of the written buffers,
+ * while write_asize accumulates the sum of b_asize rounded up
+ * to the device block size.
+ * The latter sum is used only to validate the corectness of the code.
+ */
+ uint64_t stats_size = 0;
+ write_asize = 0;
+
+ /*
* Now start writing the buffers. We're starting at the write head
* and work backwards, retracing the course of the buffer selector
* loop above.
@@ -5275,7 +5296,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
/* Compression may have squashed the buffer to zero length. */
if (buf_sz != 0) {
- uint64_t buf_p_sz;
+ uint64_t buf_a_sz;
wzio = zio_write_phys(pio, dev->l2ad_vdev,
dev->l2ad_hand, buf_sz, buf_data, ZIO_CHECKSUM_OFF,
@@ -5286,13 +5307,13 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
zio_t *, wzio);
(void) zio_nowait(wzio);
- write_asize += buf_sz;
+ stats_size += buf_sz;
/*
* Keep the clock hand suitably device-aligned.
*/
- buf_p_sz = vdev_psize_to_asize(dev->l2ad_vdev, buf_sz);
- write_psize += buf_p_sz;
- dev->l2ad_hand += buf_p_sz;
+ buf_a_sz = vdev_psize_to_asize(dev->l2ad_vdev, buf_sz);
+ write_asize += buf_a_sz;
+ dev->l2ad_hand += buf_a_sz;
}
}
@@ -5302,8 +5323,8 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
ARCSTAT_BUMP(arcstat_l2_writes_sent);
ARCSTAT_INCR(arcstat_l2_write_bytes, write_asize);
ARCSTAT_INCR(arcstat_l2_size, write_sz);
- ARCSTAT_INCR(arcstat_l2_asize, write_asize);
- vdev_space_update(dev->l2ad_vdev, write_psize, 0, 0);
+ ARCSTAT_INCR(arcstat_l2_asize, stats_size);
+ vdev_space_update(dev->l2ad_vdev, stats_size, 0, 0);
/*
* Bump device hand to the device start if it is approaching the end.
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
index af4a50f..c07737e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
@@ -4129,6 +4129,8 @@ spa_import_rootpool(const char *name)
&spa->spa_ubsync.ub_version) != 0)
spa->spa_ubsync.ub_version = SPA_VERSION_INITIAL;
} else if ((spa = spa_lookup(name)) == NULL) {
+ mutex_exit(&spa_namespace_lock);
+ nvlist_free(config);
cmn_err(CE_NOTE, "Cannot find the pool label for '%s'",
name);
return (EIO);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
index 0ebc234..b690b69 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -466,6 +466,19 @@ zfs_register_callbacks(vfs_t *vfsp)
}
/*
+ * We need to enter pool configuration here, so that we can use
+ * dsl_prop_get_int_ds() to handle the special nbmand property below.
+ * dsl_prop_get_integer() can not be used, because it has to acquire
+ * spa_namespace_lock and we can not do that because we already hold
+ * z_teardown_lock. The problem is that spa_config_sync() is called
+ * with spa_namespace_lock held and the function calls ZFS vnode
+ * operations to write the cache file and thus z_teardown_lock is
+ * acquired after spa_namespace_lock.
+ */
+ ds = dmu_objset_ds(os);
+ dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
+
+ /*
* nbmand is a special property. It can only be changed at
* mount time.
*
@@ -476,14 +489,9 @@ zfs_register_callbacks(vfs_t *vfsp)
nbmand = B_FALSE;
} else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) {
nbmand = B_TRUE;
- } else {
- char osname[MAXNAMELEN];
-
- dmu_objset_name(os, osname);
- if (error = dsl_prop_get_integer(osname, "nbmand", &nbmand,
- NULL)) {
- return (error);
- }
+ } else if (error = dsl_prop_get_int_ds(ds, "nbmand", &nbmand) != 0) {
+ dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
+ return (error);
}
/*
@@ -493,8 +501,6 @@ zfs_register_callbacks(vfs_t *vfsp)
* the first prop_register(), but I guess I like to go
* overboard...
*/
- ds = dmu_objset_ds(os);
- dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
error = dsl_prop_register(ds,
zfs_prop_to_name(ZFS_PROP_ATIME), atime_changed_cb, zfsvfs);
error = error ? error : dsl_prop_register(ds,
@@ -1700,9 +1706,19 @@ zfs_mount(vfs_t *vfsp)
* according to those options set in the current VFS options.
*/
if (vfsp->vfs_flag & MS_REMOUNT) {
- /* refresh mount options */
- zfs_unregister_callbacks(vfsp->vfs_data);
+ zfsvfs_t *zfsvfs = vfsp->vfs_data;
+
+ /*
+ * Refresh mount options with z_teardown_lock blocking I/O while
+ * the filesystem is in an inconsistent state.
+ * The lock also serializes this code with filesystem
+ * manipulations between entry to zfs_suspend_fs() and return
+ * from zfs_resume_fs().
+ */
+ rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG);
+ zfs_unregister_callbacks(zfsvfs);
error = zfs_register_callbacks(vfsp);
+ rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
goto out;
}
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 2e46808..80bb804 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -64,18 +64,15 @@ static void ata_cam_end_transaction(device_t dev, struct ata_request *request);
static void ata_cam_request_sense(device_t dev, struct ata_request *request);
static int ata_check_ids(device_t dev, union ccb *ccb);
static void ata_conn_event(void *context, int dummy);
-static void ata_init(void);
static void ata_interrupt_locked(void *data);
static int ata_module_event_handler(module_t mod, int what, void *arg);
static void ata_periodic_poll(void *data);
static int ata_str2mode(const char *str);
-static void ata_uninit(void);
/* global vars */
MALLOC_DEFINE(M_ATA, "ata_generic", "ATA driver generic layer");
int (*ata_raid_ioctl_func)(u_long cmd, caddr_t data) = NULL;
devclass_t ata_devclass;
-uma_zone_t ata_request_zone;
int ata_dma_check_80pin = 1;
/* sysctl vars */
@@ -651,12 +648,7 @@ ata_cam_begin_transaction(device_t dev, union ccb *ccb)
struct ata_channel *ch = device_get_softc(dev);
struct ata_request *request;
- if (!(request = ata_alloc_request())) {
- device_printf(dev, "FAILURE - out of memory in start\n");
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
- return;
- }
+ request = &ch->request;
bzero(request, sizeof(*request));
/* setup request */
@@ -795,7 +787,6 @@ ata_cam_process_sense(device_t dev, struct ata_request *request)
ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
}
- ata_free_request(request);
xpt_done(ccb);
/* Do error recovery if needed. */
if (fatalerr)
@@ -866,10 +857,8 @@ ata_cam_end_transaction(device_t dev, struct ata_request *request)
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR &&
(ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)
ata_cam_request_sense(dev, request);
- else {
- ata_free_request(request);
+ else
xpt_done(ccb);
- }
/* Do error recovery if needed. */
if (fatalerr)
ata_reinit(dev);
@@ -1149,18 +1138,3 @@ static moduledata_t ata_moduledata = { "ata", ata_module_event_handler, NULL };
DECLARE_MODULE(ata, ata_moduledata, SI_SUB_CONFIGURE, SI_ORDER_SECOND);
MODULE_VERSION(ata, 1);
MODULE_DEPEND(ata, cam, 1, 1, 1);
-
-static void
-ata_init(void)
-{
- ata_request_zone = uma_zcreate("ata_request", sizeof(struct ata_request),
- NULL, NULL, NULL, NULL, 0, 0);
-}
-SYSINIT(ata_register, SI_SUB_DRIVERS, SI_ORDER_SECOND, ata_init, NULL);
-
-static void
-ata_uninit(void)
-{
- uma_zdestroy(ata_request_zone);
-}
-SYSUNINIT(ata_unregister, SI_SUB_DRIVERS, SI_ORDER_SECOND, ata_uninit, NULL);
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 19cb7ef..cf8ed78 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -450,6 +450,7 @@ struct ata_channel {
struct ata_cam_device curr[16]; /* Current settings */
int requestsense; /* CCB waiting for SENSE. */
struct callout poll_callout; /* Periodic status poll. */
+ struct ata_request request;
};
/* disk bay/enclosure related */
@@ -507,14 +508,6 @@ int ata_sata_getrev(device_t dev, int target);
int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis);
void ata_pm_identify(device_t dev);
-/* macros for alloc/free of struct ata_request */
-extern uma_zone_t ata_request_zone;
-#define ata_alloc_request() uma_zalloc(ata_request_zone, M_NOWAIT | M_ZERO)
-#define ata_free_request(request) { \
- if (!(request->flags & ATA_R_DANGER2)) \
- uma_zfree(ata_request_zone, request); \
- }
-
MALLOC_DECLARE(M_ATA);
/* misc newbus defines */
diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c
index cfb24c9..a465fac 100644
--- a/sys/dev/ciss/ciss.c
+++ b/sys/dev/ciss/ciss.c
@@ -4018,8 +4018,7 @@ static void
ciss_notify_logical(struct ciss_softc *sc, struct ciss_notify *cn)
{
struct ciss_ldrive *ld;
- int bus, target;
- int rescan_ld;
+ int ostatus, bus, target;
debug_called(2);
@@ -4042,6 +4041,7 @@ ciss_notify_logical(struct ciss_softc *sc, struct ciss_notify *cn)
/*
* Update our idea of the drive's status.
*/
+ ostatus = ciss_decode_ldrive_status(cn->data.logical_status.previous_state);
ld->cl_status = ciss_decode_ldrive_status(cn->data.logical_status.new_state);
if (ld->cl_lstatus != NULL)
ld->cl_lstatus->status = cn->data.logical_status.new_state;
@@ -4049,9 +4049,7 @@ ciss_notify_logical(struct ciss_softc *sc, struct ciss_notify *cn)
/*
* Have CAM rescan the drive if its status has changed.
*/
- rescan_ld = (cn->data.logical_status.previous_state !=
- cn->data.logical_status.new_state) ? 1 : 0;
- if (rescan_ld) {
+ if (ostatus != ld->cl_status) {
ld->cl_update = 1;
ciss_notify_rescan_logical(sc);
}
diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c
index c711e3d..f8a698f 100644
--- a/sys/dev/filemon/filemon.c
+++ b/sys/dev/filemon/filemon.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2011, David E. O'Brien.
* Copyright (c) 2009-2011, Juniper Networks, Inc.
+ * Copyright (c) 2015, EMC Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,12 +40,14 @@ __FBSDID("$FreeBSD$");
#include <sys/fcntl.h>
#include <sys/ioccom.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/poll.h>
#include <sys/proc.h>
#include <sys/queue.h>
+#include <sys/sx.h>
#include <sys/syscall.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
@@ -85,12 +88,8 @@ MALLOC_DEFINE(M_FILEMON, "filemon", "File access monitor");
struct filemon {
TAILQ_ENTRY(filemon) link; /* Link into the in-use list. */
- struct mtx mtx; /* Lock mutex for this filemon. */
- struct cv cv; /* Lock condition variable for this
- filemon. */
+ struct sx lock; /* Lock mutex for this filemon. */
struct file *fp; /* Output file pointer. */
- struct thread *locker; /* Ptr to the thread locking this
- filemon. */
pid_t pid; /* The process ID being monitored. */
char fname1[MAXPATHLEN]; /* Temporary filename buffer. */
char fname2[MAXPATHLEN]; /* Temporary filename buffer. */
@@ -99,11 +98,7 @@ struct filemon {
static TAILQ_HEAD(, filemon) filemons_inuse = TAILQ_HEAD_INITIALIZER(filemons_inuse);
static TAILQ_HEAD(, filemon) filemons_free = TAILQ_HEAD_INITIALIZER(filemons_free);
-static int n_readers = 0;
-static struct mtx access_mtx;
-static struct cv access_cv;
-static struct thread *access_owner = NULL;
-static struct thread *access_requester = NULL;
+static struct sx access_lock;
static struct cdev *filemon_dev;
@@ -203,8 +198,7 @@ filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused,
filemon->fp = NULL;
- mtx_init(&filemon->mtx, "filemon", "filemon", MTX_DEF);
- cv_init(&filemon->cv, "filemon");
+ sx_init(&filemon->lock, "filemon");
}
filemon->pid = curproc->p_pid;
@@ -234,8 +228,7 @@ filemon_close(struct cdev *dev __unused, int flag __unused, int fmt __unused,
static void
filemon_load(void *dummy __unused)
{
- mtx_init(&access_mtx, "filemon", "filemon", MTX_DEF);
- cv_init(&access_cv, "filemon");
+ sx_init(&access_lock, "filemons_inuse");
/* Install the syscall wrappers. */
filemon_wrapper_install();
@@ -270,14 +263,12 @@ filemon_unload(void)
filemon_lock_write();
while ((filemon = TAILQ_FIRST(&filemons_free)) != NULL) {
TAILQ_REMOVE(&filemons_free, filemon, link);
- mtx_destroy(&filemon->mtx);
- cv_destroy(&filemon->cv);
+ sx_destroy(&filemon->lock);
free(filemon, M_FILEMON);
}
filemon_unlock_write();
- mtx_destroy(&access_mtx);
- cv_destroy(&access_cv);
+ sx_destroy(&access_lock);
}
return (error);
diff --git a/sys/dev/filemon/filemon_lock.c b/sys/dev/filemon/filemon_lock.c
index 6e836d1..a0347000 100644
--- a/sys/dev/filemon/filemon_lock.c
+++ b/sys/dev/filemon/filemon_lock.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2009-2011, Juniper Networks, Inc.
+ * Copyright (c) 2015, EMC Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,96 +28,44 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-static void
+static __inline void
filemon_filemon_lock(struct filemon *filemon)
{
- mtx_lock(&filemon->mtx);
- while (filemon->locker != NULL && filemon->locker != curthread)
- cv_wait(&filemon->cv, &filemon->mtx);
-
- filemon->locker = curthread;
-
- mtx_unlock(&filemon->mtx);
+ sx_xlock(&filemon->lock);
}
-static void
+static __inline void
filemon_filemon_unlock(struct filemon *filemon)
{
- mtx_lock(&filemon->mtx);
-
- if (filemon->locker == curthread)
- filemon->locker = NULL;
-
- /* Wake up threads waiting. */
- cv_broadcast(&filemon->cv);
- mtx_unlock(&filemon->mtx);
+ sx_xunlock(&filemon->lock);
}
-static void
+static __inline void
filemon_lock_read(void)
{
- mtx_lock(&access_mtx);
-
- while (access_owner != NULL || access_requester != NULL)
- cv_wait(&access_cv, &access_mtx);
-
- n_readers++;
-
- /* Wake up threads waiting. */
- cv_broadcast(&access_cv);
- mtx_unlock(&access_mtx);
+ sx_slock(&access_lock);
}
-static void
+static __inline void
filemon_unlock_read(void)
{
- mtx_lock(&access_mtx);
- if (n_readers > 0)
- n_readers--;
-
- /* Wake up a thread waiting. */
- cv_broadcast(&access_cv);
-
- mtx_unlock(&access_mtx);
+ sx_sunlock(&access_lock);
}
-static void
+static __inline void
filemon_lock_write(void)
{
- mtx_lock(&access_mtx);
-
- while (access_owner != curthread) {
- if (access_owner == NULL &&
- (access_requester == NULL ||
- access_requester == curthread)) {
- access_owner = curthread;
- access_requester = NULL;
- } else {
- if (access_requester == NULL)
- access_requester = curthread;
- cv_wait(&access_cv, &access_mtx);
- }
- }
-
- mtx_unlock(&access_mtx);
+ sx_xlock(&access_lock);
}
-static void
+static __inline void
filemon_unlock_write(void)
{
- mtx_lock(&access_mtx);
-
- /* Sanity check that the current thread actually has the write lock. */
- if (access_owner == curthread)
- access_owner = NULL;
-
- /* Wake up a thread waiting. */
- cv_broadcast(&access_cv);
- mtx_unlock(&access_mtx);
+ sx_xunlock(&access_lock);
}
diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c
index 4a1259a..d107a40 100644
--- a/sys/dev/filemon/filemon_wrapper.c
+++ b/sys/dev/filemon/filemon_wrapper.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2011, David E. O'Brien.
* Copyright (c) 2009-2011, Juniper Networks, Inc.
+ * Copyright (c) 2015, EMC Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -86,17 +87,25 @@ filemon_pid_check(struct proc *p)
{
struct filemon *filemon;
+ filemon_lock_read();
+ if (TAILQ_EMPTY(&filemons_inuse)) {
+ filemon_unlock_read();
+ return (NULL);
+ }
sx_slock(&proctree_lock);
while (p != initproc) {
TAILQ_FOREACH(filemon, &filemons_inuse, link) {
if (p->p_pid == filemon->pid) {
sx_sunlock(&proctree_lock);
+ filemon_filemon_lock(filemon);
+ filemon_unlock_read();
return (filemon);
}
}
p = proc_realparent(p);
}
sx_sunlock(&proctree_lock);
+ filemon_unlock_read();
return (NULL);
}
@@ -109,9 +118,6 @@ filemon_comment(struct filemon *filemon)
/* Load timestamp before locking. Less accurate but less contention. */
getmicrotime(&now);
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
/* Lock the found filemon structure. */
filemon_filemon_lock(filemon);
@@ -124,9 +130,6 @@ filemon_comment(struct filemon *filemon)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
-
- /* Release the read lock. */
- filemon_unlock_read();
}
static int
@@ -138,13 +141,7 @@ filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
struct filemon *filemon;
if ((ret = sys_chdir(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->path, filemon->fname1,
sizeof(filemon->fname1), &done);
@@ -157,9 +154,6 @@ filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -177,13 +171,7 @@ filemon_wrapper_execve(struct thread *td, struct execve_args *uap)
copyinstr(uap->fname, fname, sizeof(fname), &done);
if ((ret = sys_execve(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
len = snprintf(filemon->msgbufr,
sizeof(filemon->msgbufr), "E %d %s\n",
curproc->p_pid, fname);
@@ -193,9 +181,6 @@ filemon_wrapper_execve(struct thread *td, struct execve_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -215,13 +200,7 @@ filemon_wrapper_freebsd32_execve(struct thread *td,
copyinstr(uap->fname, fname, sizeof(fname), &done);
if ((ret = freebsd32_execve(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
len = snprintf(filemon->msgbufr,
sizeof(filemon->msgbufr), "E %d %s\n",
curproc->p_pid, fname);
@@ -231,9 +210,6 @@ filemon_wrapper_freebsd32_execve(struct thread *td,
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -248,13 +224,7 @@ filemon_wrapper_fork(struct thread *td, struct fork_args *uap)
struct filemon *filemon;
if ((ret = sys_fork(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
len = snprintf(filemon->msgbufr,
sizeof(filemon->msgbufr), "F %d %ld\n",
curproc->p_pid, (long)curthread->td_retval[0]);
@@ -264,9 +234,6 @@ filemon_wrapper_fork(struct thread *td, struct fork_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -281,13 +248,7 @@ filemon_wrapper_open(struct thread *td, struct open_args *uap)
struct filemon *filemon;
if ((ret = sys_open(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->path, filemon->fname1,
sizeof(filemon->fname1), &done);
@@ -313,9 +274,6 @@ filemon_wrapper_open(struct thread *td, struct open_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -330,13 +288,7 @@ filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
struct filemon *filemon;
if ((ret = sys_openat(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->path, filemon->fname1,
sizeof(filemon->fname1), &done);
@@ -375,9 +327,6 @@ filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -392,13 +341,7 @@ filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
struct filemon *filemon;
if ((ret = sys_rename(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->from, filemon->fname1,
sizeof(filemon->fname1), &done);
copyinstr(uap->to, filemon->fname2,
@@ -413,9 +356,6 @@ filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -430,13 +370,7 @@ filemon_wrapper_link(struct thread *td, struct link_args *uap)
struct filemon *filemon;
if ((ret = sys_link(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->path, filemon->fname1,
sizeof(filemon->fname1), &done);
copyinstr(uap->link, filemon->fname2,
@@ -451,9 +385,6 @@ filemon_wrapper_link(struct thread *td, struct link_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -468,13 +399,7 @@ filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
struct filemon *filemon;
if ((ret = sys_symlink(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->path, filemon->fname1,
sizeof(filemon->fname1), &done);
copyinstr(uap->link, filemon->fname2,
@@ -489,9 +414,6 @@ filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -507,13 +429,7 @@ filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
struct filemon *filemon;
if ((ret = sys_linkat(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->path1, filemon->fname1,
sizeof(filemon->fname1), &done);
copyinstr(uap->path2, filemon->fname2,
@@ -528,9 +444,6 @@ filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -546,13 +459,7 @@ filemon_wrapper_stat(struct thread *td, struct stat_args *uap)
struct filemon *filemon;
if ((ret = sys_stat(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->path, filemon->fname1,
sizeof(filemon->fname1), &done);
@@ -565,9 +472,6 @@ filemon_wrapper_stat(struct thread *td, struct stat_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -584,13 +488,7 @@ filemon_wrapper_freebsd32_stat(struct thread *td,
struct filemon *filemon;
if ((ret = freebsd32_stat(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->path, filemon->fname1,
sizeof(filemon->fname1), &done);
@@ -603,9 +501,6 @@ filemon_wrapper_freebsd32_stat(struct thread *td,
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -622,13 +517,7 @@ filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap)
/* Get timestamp before locking. */
getmicrotime(&now);
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr),
"X %d %d\n", curproc->p_pid, uap->rval);
@@ -649,9 +538,6 @@ filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap)
filemon_filemon_unlock(filemon);
}
- /* Release the read lock. */
- filemon_unlock_read();
-
sys_sys_exit(td, uap);
}
@@ -664,13 +550,7 @@ filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
struct filemon *filemon;
if ((ret = sys_unlink(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
copyinstr(uap->path, filemon->fname1,
sizeof(filemon->fname1), &done);
@@ -683,9 +563,6 @@ filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
@@ -699,13 +576,7 @@ filemon_wrapper_vfork(struct thread *td, struct vfork_args *uap)
struct filemon *filemon;
if ((ret = sys_vfork(td, uap)) == 0) {
- /* Grab a read lock on the filemon inuse list. */
- filemon_lock_read();
-
if ((filemon = filemon_pid_check(curproc)) != NULL) {
- /* Lock the found filemon structure. */
- filemon_filemon_lock(filemon);
-
len = snprintf(filemon->msgbufr,
sizeof(filemon->msgbufr), "F %d %ld\n",
curproc->p_pid, (long)curthread->td_retval[0]);
@@ -715,9 +586,6 @@ filemon_wrapper_vfork(struct thread *td, struct vfork_args *uap)
/* Unlock the found filemon structure. */
filemon_filemon_unlock(filemon);
}
-
- /* Release the read lock. */
- filemon_unlock_read();
}
return (ret);
diff --git a/sys/dev/ipmi/ipmi.c b/sys/dev/ipmi/ipmi.c
index a1edbf6..8101717 100644
--- a/sys/dev/ipmi/ipmi.c
+++ b/sys/dev/ipmi/ipmi.c
@@ -756,17 +756,22 @@ ipmi_startup(void *arg)
}
device_printf(dev, "Number of channels %d\n", i);
- /* probe for watchdog */
- IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
- IPMI_GET_WDOG, 0, 0);
+ /*
+ * Probe for watchdog, but only for backends which support
+ * polled driver requests.
+ */
+ if (sc->ipmi_driver_requests_polled) {
+ IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
+ IPMI_GET_WDOG, 0, 0);
- ipmi_submit_driver_request(sc, req, 0);
+ ipmi_submit_driver_request(sc, req, 0);
- if (req->ir_compcode == 0x00) {
- device_printf(dev, "Attached watchdog\n");
- /* register the watchdog event handler */
- sc->ipmi_watchdog_tag = EVENTHANDLER_REGISTER(watchdog_list,
- ipmi_wd_event, sc, 0);
+ if (req->ir_compcode == 0x00) {
+ device_printf(dev, "Attached watchdog\n");
+ /* register the watchdog event handler */
+ sc->ipmi_watchdog_tag = EVENTHANDLER_REGISTER(
+ watchdog_list, ipmi_wd_event, sc, 0);
+ }
}
sc->ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev),
diff --git a/sys/dev/ipmi/ipmi_kcs.c b/sys/dev/ipmi/ipmi_kcs.c
index 1c58646..864e9a0 100644
--- a/sys/dev/ipmi/ipmi_kcs.c
+++ b/sys/dev/ipmi/ipmi_kcs.c
@@ -520,6 +520,7 @@ ipmi_kcs_attach(struct ipmi_softc *sc)
sc->ipmi_startup = kcs_startup;
sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
sc->ipmi_driver_request = kcs_driver_request;
+ sc->ipmi_driver_requests_polled = 1;
/* See if we can talk to the controller. */
status = INB(sc, KCS_CTL_STS);
diff --git a/sys/dev/ipmi/ipmi_smic.c b/sys/dev/ipmi/ipmi_smic.c
index 4e26553..92cf14e 100644
--- a/sys/dev/ipmi/ipmi_smic.c
+++ b/sys/dev/ipmi/ipmi_smic.c
@@ -415,6 +415,7 @@ ipmi_smic_attach(struct ipmi_softc *sc)
sc->ipmi_startup = smic_startup;
sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
sc->ipmi_driver_request = smic_driver_request;
+ sc->ipmi_driver_requests_polled = 1;
/* See if we can talk to the controller. */
flags = INB(sc, SMIC_FLAGS);
diff --git a/sys/dev/ipmi/ipmivars.h b/sys/dev/ipmi/ipmivars.h
index 9d7dc32..9a0b435 100644
--- a/sys/dev/ipmi/ipmivars.h
+++ b/sys/dev/ipmi/ipmivars.h
@@ -105,6 +105,7 @@ struct ipmi_softc {
int ipmi_opened;
struct cdev *ipmi_cdev;
TAILQ_HEAD(,ipmi_request) ipmi_pending_requests;
+ int ipmi_driver_requests_polled;
eventhandler_tag ipmi_watchdog_tag;
int ipmi_watchdog_active;
struct intr_config_hook ipmi_ich;
diff --git a/sys/dev/isci/isci.c b/sys/dev/isci/isci.c
index 2f0727d..5a1066c 100644
--- a/sys/dev/isci/isci.c
+++ b/sys/dev/isci/isci.c
@@ -163,6 +163,7 @@ isci_attach(device_t device)
g_isci = isci;
isci->device = device;
+ pci_enable_busmaster(device);
isci_allocate_pci_memory(isci);
@@ -272,6 +273,7 @@ isci_detach(device_t device)
pci_release_msi(device);
}
+ pci_disable_busmaster(device);
return (0);
}
diff --git a/sys/dev/isci/isci_interrupt.c b/sys/dev/isci/isci_interrupt.c
index 52c64f7..b56fd3a 100644
--- a/sys/dev/isci/isci_interrupt.c
+++ b/sys/dev/isci/isci_interrupt.c
@@ -136,8 +136,8 @@ isci_interrupt_setup(struct isci_softc *isci)
pci_msix_count(isci->device) >= max_msix_messages) {
isci->num_interrupts = max_msix_messages;
- pci_alloc_msix(isci->device, &isci->num_interrupts);
- if (isci->num_interrupts == max_msix_messages)
+ if (pci_alloc_msix(isci->device, &isci->num_interrupts) == 0 &&
+ isci->num_interrupts == max_msix_messages)
use_msix = TRUE;
}
diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index 78f25f0..a2e71e1 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -768,9 +768,9 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
struct ifreq *ifr = (struct ifreq *) data;
#if defined(INET) || defined(INET6)
struct ifaddr *ifa = (struct ifaddr *)data;
- bool avoid_reset = FALSE;
#endif
int error = 0;
+ bool avoid_reset = FALSE;
switch (command) {
@@ -783,7 +783,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
if (ifa->ifa_addr->sa_family == AF_INET6)
avoid_reset = TRUE;
#endif
-#if defined(INET) || defined(INET6)
/*
** Calling init results in link renegotiation,
** so we avoid doing it when possible.
@@ -792,11 +791,12 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
ifp->if_flags |= IFF_UP;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
ixgbe_init(adapter);
+#if defined(INET)
if (!(ifp->if_flags & IFF_NOARP))
arp_ifinit(ifp, ifa);
+#endif
} else
error = ether_ioctl(ifp, command, data);
-#endif
break;
case SIOCSIFMTU:
IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index b1d579f..a2c7a78 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -89,6 +89,7 @@
#include <sys/vnode.h>
#include <geom/geom.h>
+#include <geom/geom_int.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -1621,9 +1622,11 @@ g_md_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
"read-only");
sbuf_printf(sb, "%s<type>%s</type>\n", indent,
type);
- if (mp->type == MD_VNODE && mp->vnode != NULL)
- sbuf_printf(sb, "%s<file>%s</file>\n",
- indent, mp->file);
+ if (mp->type == MD_VNODE && mp->vnode != NULL) {
+ sbuf_printf(sb, "%s<file>", indent);
+ g_conf_printf_escaped(sb, "%s", mp->file);
+ sbuf_printf(sb, "</file>\n");
+ }
}
}
}
diff --git a/sys/dev/nvme/nvme.c b/sys/dev/nvme/nvme.c
index 329c5e5..cc14d34 100644
--- a/sys/dev/nvme/nvme.c
+++ b/sys/dev/nvme/nvme.c
@@ -390,6 +390,15 @@ nvme_notify_fail_consumers(struct nvme_controller *ctrlr)
struct nvme_consumer *cons;
uint32_t i;
+ /*
+ * This controller failed during initialization (i.e. IDENTIFY
+ * command failed or timed out). Do not notify any nvme
+ * consumers of the failure here, since the consumer does not
+ * even know about the controller yet.
+ */
+ if (!ctrlr->is_initialized)
+ return;
+
for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
cons = &nvme_consumer[i];
if (cons->id != INVALID_CONSUMER_ID && cons->fail_fn != NULL)
diff --git a/sys/dev/sound/midi/midi.c b/sys/dev/sound/midi/midi.c
index 5537d62..f95218b 100644
--- a/sys/dev/sound/midi/midi.c
+++ b/sys/dev/sound/midi/midi.c
@@ -403,7 +403,7 @@ midi_uninit(struct snd_midi *m)
{
int err;
- err = ENXIO;
+ err = EBUSY;
mtx_lock(&midistat_lock);
mtx_lock(&m->lock);
if (m->busy) {
diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c
index 4f4abf2..744321b 100644
--- a/sys/dev/usb/controller/dwc_otg.c
+++ b/sys/dev/usb/controller/dwc_otg.c
@@ -1,6 +1,7 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 2012 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2015 Daisuke Aoyama. All rights reserved.
+ * Copyright (c) 2012-2015 Hans Petter Selasky. All rights reserved.
* Copyright (c) 2010-2011 Aleksandr Rybalko. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -152,7 +153,6 @@ static void dwc_otg_do_poll(struct usb_bus *);
static void dwc_otg_standard_done(struct usb_xfer *);
static void dwc_otg_root_intr(struct dwc_otg_softc *);
static void dwc_otg_interrupt_poll_locked(struct dwc_otg_softc *);
-static void dwc_otg_host_channel_disable(struct dwc_otg_softc *, uint8_t);
/*
* Here is a configuration that the chip supports.
@@ -225,7 +225,7 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode)
/* split equally for IN and OUT */
fifo_size /= 2;
- /* align to 4 bytes boundary */
+ /* Align to 4 bytes boundary (refer to PGM) */
fifo_size &= ~3;
/* set global receive FIFO size */
@@ -238,13 +238,6 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode)
return (EINVAL);
}
- /* disable any leftover host channels */
- for (x = 0; x != sc->sc_host_ch_max; x++) {
- if (sc->sc_chan_state[x].wait_sof == 0)
- continue;
- dwc_otg_host_channel_disable(sc, x);
- }
-
if (mode == DWC_MODE_HOST) {
/* reset active endpoints */
@@ -253,6 +246,8 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode)
/* split equally for periodic and non-periodic */
fifo_size /= 2;
+ DPRINTF("PTX/NPTX FIFO=%u\n", fifo_size);
+
/* align to 4 bytes boundary */
fifo_size &= ~3;
@@ -263,7 +258,7 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode)
tx_start += fifo_size;
for (x = 0; x != sc->sc_host_ch_max; x++) {
- /* disable all host interrupts */
+ /* enable all host interrupts */
DWC_OTG_WRITE_4(sc, DOTG_HCINTMSK(x),
HCINT_DEFAULT_MASK);
}
@@ -275,13 +270,6 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode)
/* reset host channel state */
memset(sc->sc_chan_state, 0, sizeof(sc->sc_chan_state));
- /* reset FIFO TX levels */
- sc->sc_tx_cur_p_level = 0;
- sc->sc_tx_cur_np_level = 0;
-
- /* store maximum periodic and non-periodic FIFO TX size */
- sc->sc_tx_max_size = fifo_size;
-
/* enable all host channel interrupts */
DWC_OTG_WRITE_4(sc, DOTG_HAINTMSK,
(1U << sc->sc_host_ch_max) - 1U);
@@ -314,32 +302,29 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode)
if (x < sc->sc_dev_in_ep_max) {
uint32_t limit;
- limit = (x == 1) ? DWC_OTG_MAX_TXN :
- (DWC_OTG_MAX_TXN / 2);
+ limit = (x == 1) ? MIN(DWC_OTG_TX_MAX_FIFO_SIZE,
+ DWC_OTG_MAX_TXN) : MIN(DWC_OTG_MAX_TXN / 2,
+ DWC_OTG_TX_MAX_FIFO_SIZE);
- if (fifo_size >= limit) {
- DWC_OTG_WRITE_4(sc, DOTG_DIEPTXF(x),
- ((limit / 4) << 16) |
- (tx_start / 4));
- tx_start += limit;
- fifo_size -= limit;
- pf->usb.max_in_frame_size = 0x200;
- pf->usb.support_in = 1;
+ /* see if there is enough FIFO space */
+ if (limit <= fifo_size) {
pf->max_buffer = limit;
-
- } else if (fifo_size >= 0x80) {
- DWC_OTG_WRITE_4(sc, DOTG_DIEPTXF(x),
- ((0x80 / 4) << 16) | (tx_start / 4));
- tx_start += 0x80;
- fifo_size -= 0x80;
- pf->usb.max_in_frame_size = 0x40;
pf->usb.support_in = 1;
-
} else {
- pf->usb.is_simplex = 1;
- DWC_OTG_WRITE_4(sc, DOTG_DIEPTXF(x),
- (0x0 << 16) | (tx_start / 4));
+ limit = MIN(DWC_OTG_TX_MAX_FIFO_SIZE, 0x40);
+ if (limit <= fifo_size) {
+ pf->usb.support_in = 1;
+ } else {
+ pf->usb.is_simplex = 1;
+ limit = 0;
+ }
}
+ /* set FIFO size */
+ DWC_OTG_WRITE_4(sc, DOTG_DIEPTXF(x),
+ ((limit / 4) << 16) | (tx_start / 4));
+ tx_start += limit;
+ fifo_size -= limit;
+ pf->usb.max_in_frame_size = limit;
} else {
pf->usb.is_simplex = 1;
}
@@ -362,15 +347,8 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode)
/* reset active endpoints */
sc->sc_active_rx_ep = 0;
- /* reset periodic and non-periodic FIFO TX size */
- sc->sc_tx_max_size = fifo_size;
-
/* reset host channel state */
memset(sc->sc_chan_state, 0, sizeof(sc->sc_chan_state));
-
- /* reset FIFO TX levels */
- sc->sc_tx_cur_p_level = 0;
- sc->sc_tx_cur_np_level = 0;
}
return (0);
}
@@ -476,8 +454,12 @@ static void
dwc_otg_enable_sof_irq(struct dwc_otg_softc *sc)
{
/* In device mode we don't use the SOF interrupt */
- if (sc->sc_flags.status_device_mode != 0 ||
- (sc->sc_irq_mask & GINTMSK_SOFMSK) != 0)
+ if (sc->sc_flags.status_device_mode != 0)
+ return;
+ /* Ensure the SOF interrupt is not disabled */
+ sc->sc_needsof = 1;
+ /* Check if the SOF interrupt is already enabled */
+ if ((sc->sc_irq_mask & GINTMSK_SOFMSK) != 0)
return;
sc->sc_irq_mask |= GINTMSK_SOFMSK;
DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask);
@@ -616,13 +598,48 @@ dwc_otg_clear_hcint(struct dwc_otg_softc *sc, uint8_t x)
}
static uint8_t
-dwc_otg_host_channel_alloc(struct dwc_otg_softc *sc, struct dwc_otg_td *td, uint8_t is_out)
+dwc_otg_host_check_tx_fifo_empty(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
+{
+ uint32_t temp;
+
+ temp = DWC_OTG_READ_4(sc, DOTG_GINTSTS);
+
+ if (td->ep_type == UE_ISOCHRONOUS) {
+ /*
+ * NOTE: USB INTERRUPT transactions are executed like
+ * USB CONTROL transactions! See the setup standard
+ * chain function for more information.
+ */
+ if (!(temp & GINTSTS_PTXFEMP)) {
+ DPRINTF("Periodic TX FIFO is not empty\n");
+ if (!(sc->sc_irq_mask & GINTMSK_PTXFEMPMSK)) {
+ sc->sc_irq_mask |= GINTMSK_PTXFEMPMSK;
+ DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask);
+ }
+ return (1); /* busy */
+ }
+ } else {
+ if (!(temp & GINTSTS_NPTXFEMP)) {
+ DPRINTF("Non-periodic TX FIFO is not empty\n");
+ if (!(sc->sc_irq_mask & GINTMSK_NPTXFEMPMSK)) {
+ sc->sc_irq_mask |= GINTMSK_NPTXFEMPMSK;
+ DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask);
+ }
+ return (1); /* busy */
+ }
+ }
+ return (0); /* ready for transmit */
+}
+
+static uint8_t
+dwc_otg_host_channel_alloc(struct dwc_otg_softc *sc,
+ struct dwc_otg_td *td, uint8_t is_out)
{
- uint32_t tx_p_size;
- uint32_t tx_np_size;
uint8_t x;
+ uint8_t y;
+ uint8_t z;
- if (td->channel < DWC_OTG_MAX_CHANNELS)
+ if (td->channel[0] < DWC_OTG_MAX_CHANNELS)
return (0); /* already allocated */
/* check if device is suspended */
@@ -631,45 +648,41 @@ dwc_otg_host_channel_alloc(struct dwc_otg_softc *sc, struct dwc_otg_td *td, uint
/* compute needed TX FIFO size */
if (is_out != 0) {
- if (td->ep_type == UE_ISOCHRONOUS) {
- tx_p_size = td->max_packet_size;
- tx_np_size = 0;
- if (td->hcsplt != 0 && tx_p_size > HCSPLT_XACTLEN_BURST)
- tx_p_size = HCSPLT_XACTLEN_BURST;
- if ((sc->sc_tx_cur_p_level + tx_p_size) > sc->sc_tx_max_size) {
- DPRINTF("Too little FIFO space\n");
- return (1); /* too little FIFO */
- }
- } else {
- tx_p_size = 0;
- tx_np_size = td->max_packet_size;
- if (td->hcsplt != 0 && tx_np_size > HCSPLT_XACTLEN_BURST)
- tx_np_size = HCSPLT_XACTLEN_BURST;
- if ((sc->sc_tx_cur_np_level + tx_np_size) > sc->sc_tx_max_size) {
- DPRINTF("Too little FIFO space\n");
- return (1); /* too little FIFO */
- }
- }
- } else {
- /* not a TX transaction */
- tx_p_size = 0;
- tx_np_size = 0;
+ if (dwc_otg_host_check_tx_fifo_empty(sc, td) != 0)
+ return (1); /* busy - cannot transfer data */
}
-
- for (x = 0; x != sc->sc_host_ch_max; x++) {
+ z = td->max_packet_count;
+ for (x = y = 0; x != sc->sc_host_ch_max; x++) {
+ /* check if channel is allocated */
if (sc->sc_chan_state[x].allocated != 0)
continue;
/* check if channel is still enabled */
- if (sc->sc_chan_state[x].wait_sof != 0)
+ if (sc->sc_chan_state[x].wait_halted != 0)
continue;
+ /* store channel number */
+ td->channel[y++] = x;
+ /* check if we got all channels */
+ if (y == z)
+ break;
+ }
+ if (y != z) {
+ /* reset channel variable */
+ td->channel[0] = DWC_OTG_MAX_CHANNELS;
+ td->channel[1] = DWC_OTG_MAX_CHANNELS;
+ td->channel[2] = DWC_OTG_MAX_CHANNELS;
+ /* wait a bit */
+ dwc_otg_enable_sof_irq(sc);
+ return (1); /* busy - not enough channels */
+ }
+
+ for (y = 0; y != z; y++) {
+ x = td->channel[y];
+ /* set allocated */
sc->sc_chan_state[x].allocated = 1;
- sc->sc_chan_state[x].tx_p_size = tx_p_size;
- sc->sc_chan_state[x].tx_np_size = tx_np_size;
- /* keep track of used TX FIFO, if any */
- sc->sc_tx_cur_p_level += tx_p_size;
- sc->sc_tx_cur_np_level += tx_np_size;
+ /* set wait halted */
+ sc->sc_chan_state[x].wait_halted = 1;
/* clear interrupts */
dwc_otg_clear_hcint(sc, x);
@@ -679,45 +692,29 @@ dwc_otg_host_channel_alloc(struct dwc_otg_softc *sc, struct dwc_otg_td *td, uint
/* set active channel */
sc->sc_active_rx_ep |= (1 << x);
-
- /* set channel */
- td->channel = x;
-
- return (0); /* allocated */
}
- /* wait a bit */
- dwc_otg_enable_sof_irq(sc);
- return (1); /* busy */
+ return (0); /* allocated */
}
static void
-dwc_otg_host_channel_free(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
+dwc_otg_host_channel_free_sub(struct dwc_otg_softc *sc, struct dwc_otg_td *td, uint8_t index)
{
+ uint32_t hcchar;
uint8_t x;
- if (td->channel >= DWC_OTG_MAX_CHANNELS)
+ if (td->channel[index] >= DWC_OTG_MAX_CHANNELS)
return; /* already freed */
/* free channel */
- x = td->channel;
- td->channel = DWC_OTG_MAX_CHANNELS;
+ x = td->channel[index];
+ td->channel[index] = DWC_OTG_MAX_CHANNELS;
DPRINTF("CH=%d\n", x);
/*
* We need to let programmed host channels run till complete
- * else the host channel will stop functioning. Assume that
- * after a fixed given amount of time the host channel is no
- * longer doing any USB traffic:
+ * else the host channel will stop functioning.
*/
- if (td->ep_type == UE_ISOCHRONOUS) {
- /* double buffered */
- sc->sc_chan_state[x].wait_sof = DWC_OTG_SLOT_IDLE_MAX;
- } else {
- /* single buffered */
- sc->sc_chan_state[x].wait_sof = DWC_OTG_SLOT_IDLE_MIN;
- }
-
sc->sc_chan_state[x].allocated = 0;
/* ack any pending messages */
@@ -728,17 +725,43 @@ dwc_otg_host_channel_free(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
/* clear active channel */
sc->sc_active_rx_ep &= ~(1 << x);
+
+ /* check if already halted */
+ if (sc->sc_chan_state[x].wait_halted == 0)
+ return;
+
+ /* disable host channel */
+ hcchar = DWC_OTG_READ_4(sc, DOTG_HCCHAR(x));
+ if (hcchar & HCCHAR_CHENA) {
+ DPRINTF("Halting channel %d\n", x);
+ DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(x),
+ hcchar | HCCHAR_CHDIS);
+ /* don't write HCCHAR until the channel is halted */
+ } else {
+ sc->sc_chan_state[x].wait_halted = 0;
+ }
+}
+
+static void
+dwc_otg_host_channel_free(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
+{
+ uint8_t x;
+ for (x = 0; x != td->max_packet_count; x++)
+ dwc_otg_host_channel_free_sub(sc, td, x);
}
static void
dwc_otg_host_dump_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
{
+ uint8_t x;
/* dump any pending messages */
- if (sc->sc_last_rx_status != 0) {
- if (td->channel < DWC_OTG_MAX_CHANNELS &&
- td->channel == GRXSTSRD_CHNUM_GET(sc->sc_last_rx_status)) {
- dwc_otg_common_rx_ack(sc);
- }
+ if (sc->sc_last_rx_status == 0)
+ return;
+ for (x = 0; x != td->max_packet_count; x++) {
+ if (td->channel[x] >= DWC_OTG_MAX_CHANNELS ||
+ td->channel[x] != GRXSTSRD_CHNUM_GET(sc->sc_last_rx_status))
+ continue;
+ dwc_otg_common_rx_ack(sc);
}
}
@@ -752,13 +775,13 @@ dwc_otg_host_setup_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
dwc_otg_host_dump_rx(sc, td);
- if (td->channel < DWC_OTG_MAX_CHANNELS) {
- hcint = sc->sc_chan_state[td->channel].hcint;
+ if (td->channel[0] < DWC_OTG_MAX_CHANNELS) {
+ hcint = sc->sc_chan_state[td->channel[0]].hcint;
DPRINTF("CH=%d ST=%d HCINT=0x%08x HCCHAR=0x%08x HCTSIZ=0x%08x\n",
- td->channel, td->state, hcint,
- DWC_OTG_READ_4(sc, DOTG_HCCHAR(td->channel)),
- DWC_OTG_READ_4(sc, DOTG_HCTSIZ(td->channel)));
+ td->channel[0], td->state, hcint,
+ DWC_OTG_READ_4(sc, DOTG_HCCHAR(td->channel[0])),
+ DWC_OTG_READ_4(sc, DOTG_HCTSIZ(td->channel[0])));
} else {
hcint = 0;
goto check_state;
@@ -768,12 +791,12 @@ dwc_otg_host_setup_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
HCINT_ACK | HCINT_NYET)) {
/* give success bits priority over failure bits */
} else if (hcint & HCINT_STALL) {
- DPRINTF("CH=%d STALL\n", td->channel);
+ DPRINTF("CH=%d STALL\n", td->channel[0]);
td->error_stall = 1;
td->error_any = 1;
goto complete;
} else if (hcint & HCINT_ERRORS) {
- DPRINTF("CH=%d ERROR\n", td->channel);
+ DPRINTF("CH=%d ERROR\n", td->channel[0]);
td->errcnt++;
if (td->hcsplt != 0 || td->errcnt >= 3) {
td->error_any = 1;
@@ -794,7 +817,7 @@ check_state:
case DWC_CHAN_ST_WAIT_ANE:
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & (HCINT_ACK | HCINT_NYET)) {
@@ -808,7 +831,7 @@ check_state:
case DWC_CHAN_ST_WAIT_S_ANE:
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & (HCINT_ACK | HCINT_NYET)) {
@@ -820,7 +843,7 @@ check_state:
if (hcint & HCINT_NYET) {
goto send_cpkt;
} else if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & HCINT_ACK) {
@@ -878,23 +901,23 @@ send_pkt:
usbd_copy_out(td->pc, 0, &req, sizeof(req));
- DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(td->channel),
+ DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(td->channel[0]),
(sizeof(req) << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
(HCTSIZ_PID_SETUP << HCTSIZ_PID_SHIFT));
- DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(td->channel), td->hcsplt);
+ DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(td->channel[0]), td->hcsplt);
hcchar = td->hcchar;
hcchar &= ~(HCCHAR_EPDIR_IN | HCCHAR_EPTYPE_MASK);
hcchar |= UE_CONTROL << HCCHAR_EPTYPE_SHIFT;
/* must enable channel before writing data to FIFO */
- DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel), hcchar);
+ DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel[0]), hcchar);
/* transfer data into FIFO */
bus_space_write_region_4(sc->sc_io_tag, sc->sc_io_hdl,
- DOTG_DFIFO(td->channel), (uint32_t *)&req, sizeof(req) / 4);
+ DOTG_DFIFO(td->channel[0]), (uint32_t *)&req, sizeof(req) / 4);
/* wait until next slot before trying complete split */
td->tt_complete_slot = sc->sc_last_frame_num + 1;
@@ -931,17 +954,17 @@ send_cpkt:
td->hcsplt |= HCSPLT_COMPSPLT;
td->state = DWC_CHAN_ST_WAIT_C_ANE;
- DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(td->channel),
+ DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(td->channel[0]),
(HCTSIZ_PID_SETUP << HCTSIZ_PID_SHIFT));
- DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(td->channel), td->hcsplt);
+ DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(td->channel[0]), td->hcsplt);
hcchar = td->hcchar;
hcchar &= ~(HCCHAR_EPDIR_IN | HCCHAR_EPTYPE_MASK);
hcchar |= UE_CONTROL << HCCHAR_EPTYPE_SHIFT;
/* must enable channel before writing data to FIFO */
- DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel), hcchar);
+ DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel[0]), hcchar);
busy:
return (1); /* busy */
@@ -1075,41 +1098,51 @@ dwc_otg_host_rate_check_interrupt(struct dwc_otg_softc *sc, struct dwc_otg_td *t
static uint8_t
dwc_otg_host_rate_check(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
{
+ uint8_t frame_num = (uint8_t)sc->sc_last_frame_num;
+
if (td->ep_type == UE_ISOCHRONOUS) {
/* non TT isochronous traffic */
- if ((td->tmr_val != 0) ||
- (sc->sc_last_frame_num & (td->tmr_res - 1))) {
+ if (frame_num & (td->tmr_res - 1))
goto busy;
- }
- td->tmr_val = 1; /* executed */
+ if ((frame_num ^ td->tmr_val) & td->tmr_res)
+ goto busy;
+ td->tmr_val = td->tmr_res + sc->sc_last_frame_num;
td->toggle = 0;
-
+ return (0);
} else if (td->ep_type == UE_INTERRUPT) {
if (!td->tt_scheduled)
goto busy;
td->tt_scheduled = 0;
- } else if (td->did_nak >= DWC_OTG_NAK_MAX) {
- goto busy;
+ return (0);
+ } else if (td->did_nak != 0) {
+ /* check if we should pause sending queries for 125us */
+ if (td->tmr_res == frame_num) {
+ /* wait a bit */
+ dwc_otg_enable_sof_irq(sc);
+ goto busy;
+ }
} else if (td->set_toggle) {
td->set_toggle = 0;
td->toggle = 1;
}
+ /* query for data one more time */
+ td->tmr_res = frame_num;
+ td->did_nak = 0;
return (0);
busy:
return (1);
}
static uint8_t
-dwc_otg_host_data_rx_sub(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
+dwc_otg_host_data_rx_sub(struct dwc_otg_softc *sc, struct dwc_otg_td *td,
+ uint8_t channel)
{
uint32_t count;
- uint8_t channel;
/* check endpoint status */
if (sc->sc_last_rx_status == 0)
goto busy;
- channel = td->channel;
if (channel >= DWC_OTG_MAX_CHANNELS)
goto busy;
@@ -1134,21 +1167,22 @@ dwc_otg_host_data_rx_sub(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
/* get the packet byte count */
count = GRXSTSRD_BCNT_GET(sc->sc_last_rx_status);
- /* check for isochronous transfer or high-speed bandwidth endpoint */
- if (td->ep_type == UE_ISOCHRONOUS || td->max_packet_count > 1) {
- if ((sc->sc_last_rx_status & GRXSTSRD_DPID_MASK) != GRXSTSRD_DPID_DATA0) {
+ /* check for ISOCHRONOUS endpoint */
+ if (td->ep_type == UE_ISOCHRONOUS) {
+ if ((sc->sc_last_rx_status & GRXSTSRD_DPID_MASK) !=
+ GRXSTSRD_DPID_DATA0) {
+ /* more data to be received */
td->tt_xactpos = HCSPLT_XACTPOS_MIDDLE;
} else {
+ /* all data received */
td->tt_xactpos = HCSPLT_XACTPOS_BEGIN;
-
/* verify the packet byte count */
- if (count < td->max_packet_size) {
+ if (count != td->remainder) {
/* we have a short packet */
td->short_pkt = 1;
td->got_short = 1;
}
}
- td->toggle = 0;
} else {
/* verify the packet byte count */
if (count != td->max_packet_size) {
@@ -1200,15 +1234,17 @@ complete:
static uint8_t
dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
{
- uint32_t hcint;
+ uint32_t hcint = 0;
uint32_t hcchar;
uint8_t delta;
uint8_t channel;
+ uint8_t x;
- channel = td->channel;
-
- if (channel < DWC_OTG_MAX_CHANNELS) {
- hcint = sc->sc_chan_state[channel].hcint;
+ for (x = 0; x != td->max_packet_count; x++) {
+ channel = td->channel[x];
+ if (channel >= DWC_OTG_MAX_CHANNELS)
+ continue;
+ hcint |= sc->sc_chan_state[channel].hcint;
DPRINTF("CH=%d ST=%d HCINT=0x%08x HCCHAR=0x%08x HCTSIZ=0x%08x\n",
channel, td->state, hcint,
@@ -1236,19 +1272,17 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
}
/* check channels for data, if any */
- if (dwc_otg_host_data_rx_sub(sc, td))
+ if (dwc_otg_host_data_rx_sub(sc, td, channel))
goto complete;
/* refresh interrupt status */
- hcint = sc->sc_chan_state[channel].hcint;
+ hcint |= sc->sc_chan_state[channel].hcint;
if (hcint & (HCINT_ERRORS | HCINT_RETRY |
HCINT_ACK | HCINT_NYET)) {
if (!(hcint & HCINT_ERRORS))
td->errcnt = 0;
}
- } else {
- hcint = 0;
}
switch (td->state) {
@@ -1275,8 +1309,10 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
td->toggle ^= 1;
goto receive_pkt;
}
+ } else if (td->ep_type == UE_ISOCHRONOUS) {
+ goto complete;
}
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
if (td->hcsplt != 0)
goto receive_spkt;
@@ -1298,12 +1334,12 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
if (td->ep_type == UE_ISOCHRONOUS) {
/* check if we are complete */
- if ((td->remainder == 0) ||
- (td->tt_xactpos == HCSPLT_XACTPOS_BEGIN)) {
+ if (td->tt_xactpos == HCSPLT_XACTPOS_BEGIN) {
goto complete;
+ } else {
+ /* get more packets */
+ goto busy;
}
- /* get another packet */
- goto receive_pkt;
} else {
/* check if we are complete */
if ((td->remainder == 0) || (td->got_short != 0)) {
@@ -1331,7 +1367,7 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
* case of interrupt and isochronous transfers:
*/
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto receive_spkt;
} else if (hcint & HCINT_NYET) {
@@ -1371,8 +1407,7 @@ receive_pkt:
}
/* complete split */
td->hcsplt |= HCSPLT_COMPSPLT;
- } else if (td->tt_xactpos == HCSPLT_XACTPOS_BEGIN &&
- dwc_otg_host_rate_check(sc, td)) {
+ } else if (dwc_otg_host_rate_check(sc, td)) {
td->state = DWC_CHAN_ST_WAIT_C_PKT;
goto busy;
}
@@ -1383,8 +1418,6 @@ receive_pkt:
goto busy;
}
- channel = td->channel;
-
/* set toggle, if any */
if (td->set_toggle) {
td->set_toggle = 0;
@@ -1393,27 +1426,31 @@ receive_pkt:
td->state = DWC_CHAN_ST_WAIT_ANE;
- /* receive one packet */
- DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
- (td->max_packet_size << HCTSIZ_XFERSIZE_SHIFT) |
- (1 << HCTSIZ_PKTCNT_SHIFT) |
- (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
- (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
+ for (x = 0; x != td->max_packet_count; x++) {
+ channel = td->channel[x];
- DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(channel), td->hcsplt);
+ /* receive one packet */
+ DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
+ (td->max_packet_size << HCTSIZ_XFERSIZE_SHIFT) |
+ (1 << HCTSIZ_PKTCNT_SHIFT) |
+ (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
+ (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
- hcchar = td->hcchar;
- hcchar |= HCCHAR_EPDIR_IN;
+ DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(channel), td->hcsplt);
- /* receive complete split ASAP */
- if ((sc->sc_last_frame_num & 1) != 0)
- hcchar |= HCCHAR_ODDFRM;
- else
- hcchar &= ~HCCHAR_ODDFRM;
+ hcchar = td->hcchar;
+ hcchar |= HCCHAR_EPDIR_IN;
- /* must enable channel before data can be received */
- DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);
+ /* receive complete split ASAP */
+ if ((sc->sc_last_frame_num & 1) != 0 &&
+ td->ep_type == UE_ISOCHRONOUS)
+ hcchar |= HCCHAR_ODDFRM;
+ else
+ hcchar &= ~HCCHAR_ODDFRM;
+ /* must enable channel before data can be received */
+ DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);
+ }
/* wait until next slot before trying complete split */
td->tt_complete_slot = sc->sc_last_frame_num + 1;
@@ -1442,7 +1479,7 @@ receive_spkt:
goto busy;
}
- channel = td->channel;
+ channel = td->channel[0];
td->hcsplt &= ~HCSPLT_COMPSPLT;
td->state = DWC_CHAN_ST_WAIT_S_ANE;
@@ -1454,7 +1491,8 @@ receive_spkt:
DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(channel), td->hcsplt);
/* send after next SOF event */
- if ((sc->sc_last_frame_num & 1) == 0)
+ if ((sc->sc_last_frame_num & 1) == 0 &&
+ td->ep_type == UE_ISOCHRONOUS)
td->hcchar |= HCCHAR_ODDFRM;
else
td->hcchar &= ~HCCHAR_ODDFRM;
@@ -1609,10 +1647,12 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
uint32_t hcchar;
uint8_t delta;
uint8_t channel;
+ uint8_t x;
dwc_otg_host_dump_rx(sc, td);
- channel = td->channel;
+ /* check that last channel is complete */
+ channel = td->channel[td->npkt];
if (channel < DWC_OTG_MAX_CHANNELS) {
hcint = sc->sc_chan_state[channel].hcint;
@@ -1655,14 +1695,18 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
case DWC_CHAN_ST_WAIT_ANE:
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & (HCINT_ACK | HCINT_NYET)) {
td->offset += td->tx_bytes;
td->remainder -= td->tx_bytes;
td->toggle ^= 1;
- td->did_nak = 0;
+ /* check if next response will be a NAK */
+ if (hcint & HCINT_NYET)
+ td->did_nak = 1;
+ else
+ td->did_nak = 0;
td->tt_scheduled = 0;
/* check remainder */
@@ -1681,7 +1725,7 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
case DWC_CHAN_ST_WAIT_S_ANE:
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & (HCINT_ACK | HCINT_NYET)) {
@@ -1694,7 +1738,7 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
if (hcint & HCINT_NYET) {
goto send_cpkt;
} else if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & HCINT_ACK) {
@@ -1719,33 +1763,13 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
goto send_cpkt;
case DWC_CHAN_ST_TX_WAIT_ISOC:
-
- /* Check if isochronous OUT traffic is complete */
+ /* Check if ISOCHRONOUS OUT traffic is complete */
if ((hcint & HCINT_HCH_DONE_MASK) == 0)
break;
td->offset += td->tx_bytes;
td->remainder -= td->tx_bytes;
-
- if (td->hcsplt != 0 || td->remainder == 0)
- goto complete;
-
- /* check for next packet */
- if (td->max_packet_count > 1)
- td->tt_xactpos++;
-
- /* free existing channel, if any */
- dwc_otg_host_channel_free(sc, td);
-
- td->state = DWC_CHAN_ST_TX_PKT_ISOC;
-
- /* FALLTHROUGH */
-
- case DWC_CHAN_ST_TX_PKT_ISOC:
- if (dwc_otg_host_channel_alloc(sc, td, 1))
- break;
- channel = td->channel;
- goto send_isoc_pkt;
+ goto complete;
default:
break;
}
@@ -1779,8 +1803,6 @@ send_pkt:
goto busy;
}
- channel = td->channel;
-
/* set toggle, if any */
if (td->set_toggle) {
td->set_toggle = 0;
@@ -1788,8 +1810,7 @@ send_pkt:
}
if (td->ep_type == UE_ISOCHRONOUS) {
-send_isoc_pkt:
- /* Isochronous OUT transfers don't have any ACKs */
+ /* ISOCHRONOUS OUT transfers don't have any ACKs */
td->state = DWC_CHAN_ST_TX_WAIT_ISOC;
td->hcsplt &= ~HCSPLT_COMPSPLT;
if (td->hcsplt != 0) {
@@ -1803,122 +1824,110 @@ send_isoc_pkt:
/* Update transaction position */
td->hcsplt &= ~HCSPLT_XACTPOS_MASK;
td->hcsplt |= (HCSPLT_XACTPOS_ALL << HCSPLT_XACTPOS_SHIFT);
- } else {
- /* send one packet at a time */
- count = td->max_packet_size;
- if (td->remainder < count) {
- /* we have a short packet */
- td->short_pkt = 1;
- count = td->remainder;
- }
}
} else if (td->hcsplt != 0) {
-
td->hcsplt &= ~HCSPLT_COMPSPLT;
-
/* Wait for ACK/NAK/ERR from TT */
td->state = DWC_CHAN_ST_WAIT_S_ANE;
-
- /* send one packet at a time */
- count = td->max_packet_size;
- if (td->remainder < count) {
- /* we have a short packet */
- td->short_pkt = 1;
- count = td->remainder;
- }
} else {
/* Wait for ACK/NAK/STALL from device */
td->state = DWC_CHAN_ST_WAIT_ANE;
+ }
+
+ td->tx_bytes = 0;
+
+ for (x = 0; x != td->max_packet_count; x++) {
+ uint32_t rem_bytes;
+
+ channel = td->channel[x];
/* send one packet at a time */
count = td->max_packet_size;
- if (td->remainder < count) {
+ rem_bytes = td->remainder - td->tx_bytes;
+ if (rem_bytes < count) {
/* we have a short packet */
td->short_pkt = 1;
- count = td->remainder;
+ count = rem_bytes;
}
- }
-
- /* check for High-Speed multi-packets */
- if ((td->hcsplt == 0) && (td->max_packet_count > 1)) {
- if (td->npkt == 0) {
- if (td->remainder >= (3 * td->max_packet_size))
- td->npkt = 3;
- else if (td->remainder >= (2 * td->max_packet_size))
- td->npkt = 2;
- else
- td->npkt = 1;
-
- if (td->npkt > td->max_packet_count)
- td->npkt = td->max_packet_count;
-
- td->tt_xactpos = 1; /* overload */
- }
- if (td->tt_xactpos == td->npkt) {
- if (td->npkt == 1) {
+ if (count == rem_bytes) {
+ /* last packet */
+ switch (x) {
+ case 0:
DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
(count << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
- (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT));
- } else if (td->npkt == 2) {
+ (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
+ (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
+ break;
+ case 1:
DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
(count << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
(HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT));
- } else {
+ break;
+ default:
DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
(count << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
(HCTSIZ_PID_DATA2 << HCTSIZ_PID_SHIFT));
+ break;
}
- td->npkt = 0;
- } else {
+ } else if (td->ep_type == UE_ISOCHRONOUS &&
+ td->max_packet_count > 1) {
+ /* ISOCHRONOUS multi packet */
DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
(count << HCTSIZ_XFERSIZE_SHIFT) |
(1 << HCTSIZ_PKTCNT_SHIFT) |
(HCTSIZ_PID_MDATA << HCTSIZ_PID_SHIFT));
+ } else {
+ /* TODO: HCTSIZ_DOPNG */
+ /* standard BULK/INTERRUPT/CONTROL packet */
+ DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
+ (count << HCTSIZ_XFERSIZE_SHIFT) |
+ (1 << HCTSIZ_PKTCNT_SHIFT) |
+ (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
+ (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
}
- } else {
- /* TODO: HCTSIZ_DOPNG */
- DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(channel),
- (count << HCTSIZ_XFERSIZE_SHIFT) |
- (1 << HCTSIZ_PKTCNT_SHIFT) |
- (td->toggle ? (HCTSIZ_PID_DATA1 << HCTSIZ_PID_SHIFT) :
- (HCTSIZ_PID_DATA0 << HCTSIZ_PID_SHIFT)));
- }
+ DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(channel), td->hcsplt);
- DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(channel), td->hcsplt);
+ hcchar = td->hcchar;
+ hcchar &= ~HCCHAR_EPDIR_IN;
- hcchar = td->hcchar;
- hcchar &= ~HCCHAR_EPDIR_IN;
+ /* send after next SOF event */
+ if ((sc->sc_last_frame_num & 1) == 0 &&
+ td->ep_type == UE_ISOCHRONOUS)
+ hcchar |= HCCHAR_ODDFRM;
+ else
+ hcchar &= ~HCCHAR_ODDFRM;
- /* send after next SOF event */
- if ((sc->sc_last_frame_num & 1) == 0)
- hcchar |= HCCHAR_ODDFRM;
- else
- hcchar &= ~HCCHAR_ODDFRM;
+ /* must enable before writing data to FIFO */
+ DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);
- /* must enable before writing data to FIFO */
- DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(channel), hcchar);
+ if (count != 0) {
+ /* clear topmost word before copy */
+ sc->sc_tx_bounce_buffer[(count - 1) / 4] = 0;
- if (count != 0) {
+ /* copy out data */
+ usbd_copy_out(td->pc, td->offset + td->tx_bytes,
+ sc->sc_tx_bounce_buffer, count);
- /* clear topmost word before copy */
- sc->sc_tx_bounce_buffer[(count - 1) / 4] = 0;
+ /* transfer data into FIFO */
+ bus_space_write_region_4(sc->sc_io_tag, sc->sc_io_hdl,
+ DOTG_DFIFO(channel),
+ sc->sc_tx_bounce_buffer, (count + 3) / 4);
+ }
- /* copy out data */
- usbd_copy_out(td->pc, td->offset,
- sc->sc_tx_bounce_buffer, count);
+ /* store number of bytes transmitted */
+ td->tx_bytes += count;
- /* transfer data into FIFO */
- bus_space_write_region_4(sc->sc_io_tag, sc->sc_io_hdl,
- DOTG_DFIFO(channel),
- sc->sc_tx_bounce_buffer, (count + 3) / 4);
+ /* store last packet index */
+ td->npkt = x;
+
+ /* check for last packet */
+ if (count == rem_bytes)
+ break;
}
-
- /* store number of bytes transmitted */
- td->tx_bytes = count;
goto busy;
send_cpkt:
@@ -1944,7 +1953,7 @@ send_cpkt:
goto busy;
}
- channel = td->channel;
+ channel = td->channel[0];
td->hcsplt |= HCSPLT_COMPSPLT;
td->state = DWC_CHAN_ST_WAIT_C_ANE;
@@ -1958,7 +1967,8 @@ send_cpkt:
hcchar &= ~HCCHAR_EPDIR_IN;
/* receive complete split ASAP */
- if ((sc->sc_last_frame_num & 1) != 0)
+ if ((sc->sc_last_frame_num & 1) != 0 &&
+ td->ep_type == UE_ISOCHRONOUS)
hcchar |= HCCHAR_ODDFRM;
else
hcchar &= ~HCCHAR_ODDFRM;
@@ -2295,8 +2305,6 @@ static void
dwc_otg_timer(void *_sc)
{
struct dwc_otg_softc *sc = _sc;
- struct usb_xfer *xfer;
- struct dwc_otg_td *td;
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
@@ -2307,14 +2315,6 @@ dwc_otg_timer(void *_sc)
/* increment timer value */
sc->sc_tmr_val++;
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- td = xfer->td_transfer_cache;
- if (td != NULL) {
- /* reset NAK counter */
- td->did_nak = 0;
- }
- }
-
/* enable SOF interrupt, which will poll jobs */
dwc_otg_enable_sof_irq(sc);
@@ -2354,31 +2354,6 @@ dwc_otg_timer_stop(struct dwc_otg_softc *sc)
usb_callout_stop(&sc->sc_timer);
}
-static void
-dwc_otg_host_channel_disable(struct dwc_otg_softc *sc, uint8_t x)
-{
- uint32_t hcchar;
-
- hcchar = DWC_OTG_READ_4(sc, DOTG_HCCHAR(x));
-
- /* disable host channel, if any */
- if (hcchar & (HCCHAR_CHENA | HCCHAR_CHDIS)) {
- /* disable channel */
- DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(x),
- HCCHAR_CHENA | HCCHAR_CHDIS);
- /* wait for chip to get its brains in order */
- sc->sc_chan_state[x].wait_sof = 2;
- }
-
- /* release TX FIFO usage, if any */
- sc->sc_tx_cur_p_level -= sc->sc_chan_state[x].tx_p_size;
- sc->sc_tx_cur_np_level -= sc->sc_chan_state[x].tx_np_size;
-
- /* don't release TX FIFO usage twice */
- sc->sc_chan_state[x].tx_p_size = 0;
- sc->sc_chan_state[x].tx_np_size = 0;
-}
-
static uint16_t
dwc_otg_compute_isoc_rx_tt_slot(struct dwc_otg_tt_info *pinfo)
{
@@ -2396,7 +2371,6 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
struct dwc_otg_td *td;
uint16_t temp;
uint16_t slot;
- uint8_t x;
temp = DWC_OTG_READ_4(sc, DOTG_HFNUM) & DWC_OTG_FRAME_MASK;
@@ -2407,15 +2381,6 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
TAILQ_INIT(&head);
- for (x = 0; x != sc->sc_host_ch_max; x++) {
- if (sc->sc_chan_state[x].wait_sof == 0)
- continue;
-
- sc->sc_needsof = 1;
- if (--(sc->sc_chan_state[x].wait_sof) == 0)
- dwc_otg_host_channel_disable(sc, x);
- }
-
if ((temp & 7) == 0) {
/* reset the schedule */
@@ -2430,9 +2395,6 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
if ((td->hcchar & HCCHAR_EPDIR_IN) != 0)
continue;
- /* execute more frames */
- td->tmr_val = 0;
-
sc->sc_needsof = 1;
if (td->hcsplt == 0 || td->tt_scheduled != 0)
@@ -2464,9 +2426,6 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
if ((td->hcchar & HCCHAR_EPDIR_IN) == 0)
continue;
- /* execute more frames */
- td->tmr_val = 0;
-
sc->sc_needsof = 1;
if (td->hcsplt == 0 || td->tt_scheduled != 0)
@@ -2509,8 +2468,7 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
TAILQ_FOREACH_SAFE(xfer, &sc->sc_bus.intr_q.head, wait_entry, xfer_next) {
td = xfer->td_transfer_cache;
if (td == NULL ||
- td->ep_type != UE_CONTROL ||
- td->did_nak >= DWC_OTG_NAK_MAX) {
+ td->ep_type != UE_CONTROL) {
continue;
}
@@ -2530,8 +2488,7 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
TAILQ_FOREACH_SAFE(xfer, &sc->sc_bus.intr_q.head, wait_entry, xfer_next) {
td = xfer->td_transfer_cache;
if (td == NULL ||
- td->ep_type != UE_BULK ||
- td->did_nak >= DWC_OTG_NAK_MAX) {
+ td->ep_type != UE_BULK) {
continue;
}
@@ -2562,10 +2519,10 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
TAILQ_CONCAT(&head, &sc->sc_bus.intr_q.head, wait_entry);
TAILQ_CONCAT(&sc->sc_bus.intr_q.head, &head, wait_entry);
- /* put non-TT BULK transfers last */
+ /* put non-TT non-ISOCHRONOUS transfers last */
TAILQ_FOREACH_SAFE(xfer, &sc->sc_bus.intr_q.head, wait_entry, xfer_next) {
td = xfer->td_transfer_cache;
- if (td == NULL || td->hcsplt != 0 || td->ep_type != UE_BULK)
+ if (td == NULL || td->hcsplt != 0 || td->ep_type == UE_ISOCHRONOUS)
continue;
TAILQ_REMOVE(&sc->sc_bus.intr_q.head, xfer, wait_entry);
TAILQ_INSERT_TAIL(&head, xfer, wait_entry);
@@ -2600,12 +2557,26 @@ static void
dwc_otg_interrupt_poll_locked(struct dwc_otg_softc *sc)
{
struct usb_xfer *xfer;
+ uint32_t count;
uint32_t temp;
uint8_t got_rx_status;
uint8_t x;
+ if (sc->sc_flags.status_device_mode == 0) {
+ /*
+ * Update host transfer schedule, so that new
+ * transfers can be issued:
+ */
+ dwc_otg_update_host_transfer_schedule_locked(sc);
+ }
+ count = 0;
repeat:
- /* get all channel interrupts */
+ if (++count == 16) {
+ /* give other interrupts a chance */
+ DPRINTF("Yield\n");
+ return;
+ }
+ /* get all host channel interrupts */
for (x = 0; x != sc->sc_host_ch_max; x++) {
temp = DWC_OTG_READ_4(sc, DOTG_HCINT(x));
if (temp != 0) {
@@ -2635,6 +2606,12 @@ repeat:
if (temp != GRXSTSRD_STP_DATA &&
temp != GRXSTSRD_STP_COMPLETE &&
temp != GRXSTSRD_OUT_DATA) {
+ /* check for halted channel */
+ if (temp == GRXSTSRH_HALTED) {
+ ep_no = GRXSTSRD_CHNUM_GET(sc->sc_last_rx_status);
+ sc->sc_chan_state[ep_no].wait_halted = 0;
+ DPRINTFN(5, "channel halt complete ch=%u\n", ep_no);
+ }
dwc_otg_common_rx_ack(sc);
goto repeat;
}
@@ -2696,12 +2673,6 @@ repeat:
sc->sc_irq_mask &= ~GINTMSK_RXFLVLMSK;
DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask);
}
-
- if (sc->sc_flags.status_device_mode == 0 && sc->sc_xfer_complete == 0) {
- /* update host transfer schedule, so that new transfers can be issued */
- if (dwc_otg_update_host_transfer_schedule_locked(sc))
- goto repeat;
- }
}
static void
@@ -2763,6 +2734,12 @@ dwc_otg_filter_interrupt(void *arg)
if ((status & DWC_OTG_MSK_GINT_THREAD_IRQ) != 0)
retval = FILTER_SCHEDULE_THREAD;
+ /* clear FIFO empty interrupts */
+ if (status & sc->sc_irq_mask &
+ (GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP)) {
+ sc->sc_irq_mask &= ~(GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP);
+ DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask);
+ }
/* clear all IN endpoint interrupts */
if (status & GINTSTS_IEPINT) {
uint32_t temp;
@@ -2970,12 +2947,6 @@ dwc_otg_interrupt(void *arg)
/* complete FIFOs, if any */
dwc_otg_interrupt_complete_locked(sc);
-
- if (sc->sc_flags.status_device_mode == 0) {
- /* update host transfer schedule, so that new transfers can be issued */
- if (dwc_otg_update_host_transfer_schedule_locked(sc))
- dwc_otg_interrupt_poll_locked(sc);
- }
}
USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
USB_BUS_UNLOCK(&sc->sc_bus);
@@ -3008,7 +2979,9 @@ dwc_otg_setup_standard_chain_sub(struct dwc_otg_std_temp *temp)
td->set_toggle = 0;
td->got_short = 0;
td->did_nak = 0;
- td->channel = DWC_OTG_MAX_CHANNELS;
+ td->channel[0] = DWC_OTG_MAX_CHANNELS;
+ td->channel[1] = DWC_OTG_MAX_CHANNELS;
+ td->channel[2] = DWC_OTG_MAX_CHANNELS;
td->state = 0;
td->errcnt = 0;
td->tt_scheduled = 0;
@@ -3273,21 +3246,21 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer)
td->tmr_val = sc->sc_tmr_val + ival;
td->tmr_res = ival;
} else if (td->ep_type == UE_ISOCHRONOUS) {
- td->tmr_val = 0;
td->tmr_res = 1;
+ td->tmr_val = sc->sc_last_frame_num;
+ if (td->hcchar & HCCHAR_EPDIR_IN)
+ td->tmr_val++;
} else {
td->tmr_val = 0;
- td->tmr_res = 0;
+ td->tmr_res = (uint8_t)sc->sc_last_frame_num;
}
break;
case USB_SPEED_HIGH:
hcsplt = 0;
if (td->ep_type == UE_INTERRUPT) {
uint32_t ival;
-#if 0
hcchar |= ((xfer->max_packet_count & 3)
<< HCCHAR_MC_SHIFT);
-#endif
ival = xfer->interval / DWC_OTG_HOST_TIMER_RATE;
if (ival == 0)
ival = 1;
@@ -3298,11 +3271,14 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer)
} else if (td->ep_type == UE_ISOCHRONOUS) {
hcchar |= ((xfer->max_packet_count & 3)
<< HCCHAR_MC_SHIFT);
- td->tmr_val = 0;
td->tmr_res = 1 << usbd_xfer_get_fps_shift(xfer);
+ td->tmr_val = sc->sc_last_frame_num;
+ if (td->hcchar & HCCHAR_EPDIR_IN)
+ td->tmr_val += td->tmr_res;
+
} else {
td->tmr_val = 0;
- td->tmr_res = 0;
+ td->tmr_res = (uint8_t)sc->sc_last_frame_num;
}
break;
default:
@@ -3342,8 +3318,6 @@ static void
dwc_otg_start_standard_chain(struct usb_xfer *xfer)
{
struct dwc_otg_softc *sc = DWC_OTG_BUS2SC(xfer->xroot->bus);
- struct usb_xfer_root *xroot;
- struct dwc_otg_td *td;
DPRINTFN(9, "\n");
@@ -3358,6 +3332,19 @@ dwc_otg_start_standard_chain(struct usb_xfer *xfer)
dwc_otg_xfer_do_fifo(sc, xfer);
if (dwc_otg_xfer_do_complete_locked(sc, xfer))
goto done;
+ } else {
+ struct dwc_otg_td *td = xfer->td_transfer_cache;
+ if (td->ep_type == UE_ISOCHRONOUS &&
+ (td->hcchar & HCCHAR_EPDIR_IN) == 0) {
+ /*
+ * Need to start ISOCHRONOUS OUT transfer ASAP
+ * because execution is delayed by one 125us
+ * microframe:
+ */
+ dwc_otg_xfer_do_fifo(sc, xfer);
+ if (dwc_otg_xfer_do_complete_locked(sc, xfer))
+ goto done;
+ }
}
/* put transfer on interrupt queue */
@@ -3374,24 +3361,6 @@ dwc_otg_start_standard_chain(struct usb_xfer *xfer)
/* enable SOF interrupt, if any */
dwc_otg_enable_sof_irq(sc);
-
- td = xfer->td_transfer_cache;
- if (td->ep_type != UE_BULK)
- goto done;
-
- xroot = xfer->xroot;
-
- /*
- * Optimise the ping-pong effect by waking up other BULK
- * transfers belonging to the same device group:
- */
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- td = xfer->td_transfer_cache;
- if (td == NULL || td->ep_type != UE_BULK || xfer->xroot != xroot)
- continue;
- /* reset NAK counter */
- td->did_nak = 0;
- }
done:
USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
}
@@ -3996,11 +3965,6 @@ dwc_otg_do_poll(struct usb_bus *bus)
USB_BUS_SPIN_LOCK(&sc->sc_bus);
dwc_otg_interrupt_poll_locked(sc);
dwc_otg_interrupt_complete_locked(sc);
- if (sc->sc_flags.status_device_mode == 0) {
- /* update host transfer schedule, so that new transfers can be issued */
- if (dwc_otg_update_host_transfer_schedule_locked(sc))
- dwc_otg_interrupt_poll_locked(sc);
- }
USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -4774,6 +4738,9 @@ dwc_otg_xfer_setup(struct usb_setup_params *parm)
/* init TD */
td->max_packet_size = xfer->max_packet_size;
td->max_packet_count = xfer->max_packet_count;
+ /* range check */
+ if (td->max_packet_count == 0 || td->max_packet_count > 3)
+ td->max_packet_count = 1;
td->ep_no = ep_no;
td->ep_type = ep_type;
td->obj_next = last_obj;
@@ -4812,12 +4779,13 @@ dwc_otg_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc,
return;
}
} else {
- if (udev->speed == USB_SPEED_HIGH) {
- if ((UGETW(edesc->wMaxPacketSize) >> 11) & 3) {
- /* high bandwidth endpoint - not tested */
- DPRINTF("High Bandwidth Endpoint - not tested\n");
- return;
- }
+ if (udev->speed == USB_SPEED_HIGH &&
+ (edesc->wMaxPacketSize[1] & 0x18) != 0 &&
+ (edesc->bmAttributes & UE_XFERTYPE) != UE_ISOCHRONOUS) {
+ /* not supported */
+ DPRINTFN(-1, "Non-isochronous high bandwidth "
+ "endpoint not supported\n");
+ return;
}
}
if ((edesc->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS)
diff --git a/sys/dev/usb/controller/dwc_otg.h b/sys/dev/usb/controller/dwc_otg.h
index 1fa1bbf..f5e9887 100644
--- a/sys/dev/usb/controller/dwc_otg.h
+++ b/sys/dev/usb/controller/dwc_otg.h
@@ -37,7 +37,9 @@
#define DWC_OTG_TT_SLOT_MAX 8
#define DWC_OTG_SLOT_IDLE_MAX 3
#define DWC_OTG_SLOT_IDLE_MIN 2
-#define DWC_OTG_NAK_MAX 8 /* 1 ms */
+#ifndef DWC_OTG_TX_MAX_FIFO_SIZE
+#define DWC_OTG_TX_MAX_FIFO_SIZE DWC_OTG_MAX_TXN
+#endif
#define DWC_OTG_READ_4(sc, reg) \
bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
@@ -65,10 +67,9 @@ struct dwc_otg_td {
uint8_t errcnt;
uint8_t tmr_res;
uint8_t tmr_val;
- uint8_t did_nak; /* NAK counter */
uint8_t ep_no;
uint8_t ep_type;
- uint8_t channel;
+ uint8_t channel[3];
uint8_t tt_index; /* TT data */
uint8_t tt_start_slot; /* TT data */
uint8_t tt_complete_slot; /* TT data */
@@ -79,8 +80,7 @@ struct dwc_otg_td {
#define DWC_CHAN_ST_WAIT_S_ANE 2
#define DWC_CHAN_ST_WAIT_C_ANE 3
#define DWC_CHAN_ST_WAIT_C_PKT 4
-#define DWC_CHAN_ST_TX_PKT_ISOC 5
-#define DWC_CHAN_ST_TX_WAIT_ISOC 6
+#define DWC_CHAN_ST_TX_WAIT_ISOC 5
uint8_t error_any:1;
uint8_t error_stall:1;
uint8_t alt_next:1;
@@ -90,6 +90,7 @@ struct dwc_otg_td {
uint8_t set_toggle:1;
uint8_t got_short:1;
uint8_t tt_scheduled:1;
+ uint8_t did_nak:1;
};
struct dwc_otg_tt_info {
@@ -153,10 +154,8 @@ struct dwc_otg_profile {
struct dwc_otg_chan_state {
uint16_t allocated;
- uint16_t wait_sof;
+ uint16_t wait_halted;
uint32_t hcint;
- uint16_t tx_p_size; /* periodic */
- uint16_t tx_np_size; /* non-periodic */
};
struct dwc_otg_softc {
@@ -178,9 +177,6 @@ struct dwc_otg_softc {
uint32_t sc_tx_bounce_buffer[MAX(512 * DWC_OTG_MAX_TXP, 1024) / 4];
uint32_t sc_fifo_size;
- uint32_t sc_tx_max_size;
- uint32_t sc_tx_cur_p_level; /* periodic */
- uint32_t sc_tx_cur_np_level; /* non-periodic */
uint32_t sc_irq_mask;
uint32_t sc_last_rx_status;
uint32_t sc_out_ctl[DWC_OTG_MAX_ENDPOINTS];
diff --git a/sys/dev/usb/controller/dwc_otgreg.h b/sys/dev/usb/controller/dwc_otgreg.h
index 8ab3582..8b9538a 100644
--- a/sys/dev/usb/controller/dwc_otgreg.h
+++ b/sys/dev/usb/controller/dwc_otgreg.h
@@ -47,6 +47,8 @@
#define DOTG_GGPIO 0x0038
#define DOTG_GUID 0x003C
#define DOTG_GSNPSID 0x0040
+#define DOTG_GSNPSID_REV_2_80a 0x4f54280a /* RPi model B/RPi2 */
+#define DOTG_GSNPSID_REV_3_10a 0x4f54310a /* ODROID-C1 */
#define DOTG_GHWCFG1 0x0044
#define DOTG_GHWCFG2 0x0048
#define DOTG_GHWCFG3 0x004C
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index f67c94d..1852467 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -233,7 +233,8 @@ usb_detach(device_t dev)
/* Get rid of USB callback processes */
usb_proc_free(USB_BUS_GIANT_PROC(bus));
- usb_proc_free(USB_BUS_NON_GIANT_PROC(bus));
+ usb_proc_free(USB_BUS_NON_GIANT_ISOC_PROC(bus));
+ usb_proc_free(USB_BUS_NON_GIANT_BULK_PROC(bus));
/* Get rid of USB explore process */
@@ -397,7 +398,8 @@ usb_bus_explore(struct usb_proc_msg *pm)
*/
usb_proc_rewakeup(USB_BUS_CONTROL_XFER_PROC(bus));
usb_proc_rewakeup(USB_BUS_GIANT_PROC(bus));
- usb_proc_rewakeup(USB_BUS_NON_GIANT_PROC(bus));
+ usb_proc_rewakeup(USB_BUS_NON_GIANT_ISOC_PROC(bus));
+ usb_proc_rewakeup(USB_BUS_NON_GIANT_BULK_PROC(bus));
#endif
USB_BUS_UNLOCK(bus);
@@ -862,9 +864,13 @@ usb_attach_sub(device_t dev, struct usb_bus *bus)
&bus->bus_mtx, device_get_nameunit(dev), USB_PRI_MED)) {
device_printf(dev, "WARNING: Creation of USB Giant "
"callback process failed.\n");
- } else if (usb_proc_create(USB_BUS_NON_GIANT_PROC(bus),
+ } else if (usb_proc_create(USB_BUS_NON_GIANT_ISOC_PROC(bus),
+ &bus->bus_mtx, device_get_nameunit(dev), USB_PRI_HIGHEST)) {
+ device_printf(dev, "WARNING: Creation of USB non-Giant ISOC "
+ "callback process failed.\n");
+ } else if (usb_proc_create(USB_BUS_NON_GIANT_BULK_PROC(bus),
&bus->bus_mtx, device_get_nameunit(dev), USB_PRI_HIGH)) {
- device_printf(dev, "WARNING: Creation of USB non-Giant "
+ device_printf(dev, "WARNING: Creation of USB non-Giant BULK "
"callback process failed.\n");
} else if (usb_proc_create(USB_BUS_EXPLORE_PROC(bus),
&bus->bus_mtx, device_get_nameunit(dev), USB_PRI_MED)) {
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index aba96dc..1c8f3b5 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -492,6 +492,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(SIERRA, AC595U, 0),
U3G_DEV(SIERRA, AC313U, 0),
U3G_DEV(SIERRA, AC597E, 0),
+ U3G_DEV(SIERRA, AC875, 0),
U3G_DEV(SIERRA, AC875E, 0),
U3G_DEV(SIERRA, AC875U, 0),
U3G_DEV(SIERRA, AC875U_2, 0),
@@ -506,7 +507,6 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(SIERRA, AC885U, 0),
U3G_DEV(SIERRA, AIRCARD580, 0),
U3G_DEV(SIERRA, AIRCARD595, 0),
- U3G_DEV(SIERRA, AIRCARD875, 0),
U3G_DEV(SIERRA, C22, 0),
U3G_DEV(SIERRA, C597, 0),
U3G_DEV(SIERRA, C888, 0),
diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h
index afc20f4..e9d4048 100644
--- a/sys/dev/usb/usb_bus.h
+++ b/sys/dev/usb/usb_bus.h
@@ -57,19 +57,26 @@ struct usb_bus {
struct root_hold_token *bus_roothold;
#endif
+/* convenience macros */
+#define USB_BUS_TT_PROC(bus) USB_BUS_NON_GIANT_ISOC_PROC(bus)
+#define USB_BUS_CS_PROC(bus) USB_BUS_NON_GIANT_ISOC_PROC(bus)
+
#if USB_HAVE_PER_BUS_PROCESS
#define USB_BUS_GIANT_PROC(bus) (&(bus)->giant_callback_proc)
-#define USB_BUS_NON_GIANT_PROC(bus) (&(bus)->non_giant_callback_proc)
+#define USB_BUS_NON_GIANT_ISOC_PROC(bus) (&(bus)->non_giant_isoc_callback_proc)
+#define USB_BUS_NON_GIANT_BULK_PROC(bus) (&(bus)->non_giant_bulk_callback_proc)
#define USB_BUS_EXPLORE_PROC(bus) (&(bus)->explore_proc)
#define USB_BUS_CONTROL_XFER_PROC(bus) (&(bus)->control_xfer_proc)
-
/*
- * There are two callback processes. One for Giant locked
- * callbacks. One for non-Giant locked callbacks. This should
- * avoid congestion and reduce response time in most cases.
+ * There are three callback processes. One for Giant locked
+ * callbacks. One for non-Giant locked non-periodic callbacks
+ * and one for non-Giant locked periodic callbacks. This
+ * should avoid congestion and reduce response time in most
+ * cases.
*/
struct usb_process giant_callback_proc;
- struct usb_process non_giant_callback_proc;
+ struct usb_process non_giant_isoc_callback_proc;
+ struct usb_process non_giant_bulk_callback_proc;
/* Explore process */
struct usb_process explore_proc;
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index c3936f6..3e29aa4 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -2184,7 +2184,7 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
* anywhere:
*/
USB_BUS_LOCK(udev->bus);
- usb_proc_mwait(USB_BUS_NON_GIANT_PROC(udev->bus),
+ usb_proc_mwait(USB_BUS_CS_PROC(udev->bus),
&udev->cs_msg[0], &udev->cs_msg[1]);
USB_BUS_UNLOCK(udev->bus);
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index 1c8682b..354e62d 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -349,7 +349,7 @@ uhub_tt_buffer_reset_async_locked(struct usb_device *child, struct usb_endpoint
}
up->req_reset_tt = req;
/* get reset transfer started */
- usb_proc_msignal(USB_BUS_NON_GIANT_PROC(udev->bus),
+ usb_proc_msignal(USB_BUS_TT_PROC(udev->bus),
&hub->tt_msg[0], &hub->tt_msg[1]);
}
#endif
@@ -1592,7 +1592,7 @@ uhub_detach(device_t dev)
#if USB_HAVE_TT_SUPPORT
/* Make sure our TT messages are not queued anywhere */
USB_BUS_LOCK(bus);
- usb_proc_mwait(USB_BUS_NON_GIANT_PROC(bus),
+ usb_proc_mwait(USB_BUS_TT_PROC(bus),
&hub->tt_msg[0], &hub->tt_msg[1]);
USB_BUS_UNLOCK(bus);
#endif
diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c
index 27ab5f7..8c47e79 100644
--- a/sys/dev/usb/usb_pf.c
+++ b/sys/dev/usb/usb_pf.c
@@ -220,7 +220,13 @@ usbpf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
ubus = ifp->if_softc;
unit = ifp->if_dunit;
+ /*
+ * Lock USB before clearing the "ifp" pointer, to avoid
+ * clearing the pointer in the middle of a TAP operation:
+ */
+ USB_BUS_LOCK(ubus);
ubus->ifp = NULL;
+ USB_BUS_UNLOCK(ubus);
bpfdetach(ifp);
if_detach(ifp);
if_free(ifp);
diff --git a/sys/dev/usb/usb_process.h b/sys/dev/usb/usb_process.h
index c12cdc4..dd20afd 100644
--- a/sys/dev/usb/usb_process.h
+++ b/sys/dev/usb/usb_process.h
@@ -34,6 +34,7 @@
#endif
/* defines */
+#define USB_PRI_HIGHEST PI_SWI(SWI_TTY)
#define USB_PRI_HIGH PI_SWI(SWI_NET)
#define USB_PRI_MED PI_SWI(SWI_CAMBIO)
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index c5815f7..53face6 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -872,6 +872,19 @@ done:
}
}
+static uint8_t
+usbd_transfer_setup_has_bulk(const struct usb_config *setup_start,
+ uint16_t n_setup)
+{
+ while (n_setup--) {
+ uint8_t type = setup_start[n_setup].type;
+ if (type == UE_BULK || type == UE_BULK_INTR ||
+ type == UE_TYPE_ANY)
+ return (1);
+ }
+ return (0);
+}
+
/*------------------------------------------------------------------------*
* usbd_transfer_setup - setup an array of USB transfers
*
@@ -1013,9 +1026,12 @@ usbd_transfer_setup(struct usb_device *udev,
else if (xfer_mtx == &Giant)
info->done_p =
USB_BUS_GIANT_PROC(udev->bus);
+ else if (usbd_transfer_setup_has_bulk(setup_start, n_setup))
+ info->done_p =
+ USB_BUS_NON_GIANT_BULK_PROC(udev->bus);
else
info->done_p =
- USB_BUS_NON_GIANT_PROC(udev->bus);
+ USB_BUS_NON_GIANT_ISOC_PROC(udev->bus);
}
/* reset sizes */
@@ -2280,10 +2296,8 @@ usbd_callback_ss_done_defer(struct usb_xfer *xfer)
* will have a Lock Order Reversal, LOR, if we try to
* proceed !
*/
- if (usb_proc_msignal(info->done_p,
- &info->done_m[0], &info->done_m[1])) {
- /* ignore */
- }
+ (void) usb_proc_msignal(info->done_p,
+ &info->done_m[0], &info->done_m[1]);
} else {
/* clear second recurse flag */
pq->recurse_2 = 0;
@@ -2307,23 +2321,26 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq)
struct usb_xfer_root *info = xfer->xroot;
USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
- if (!mtx_owned(info->xfer_mtx) && !SCHEDULER_STOPPED()) {
+ if ((pq->recurse_3 != 0 || mtx_owned(info->xfer_mtx) == 0) &&
+ SCHEDULER_STOPPED() == 0) {
/*
* Cases that end up here:
*
* 5) HW interrupt done callback or other source.
+ * 6) HW completed transfer during callback
*/
- DPRINTFN(3, "case 5\n");
+ DPRINTFN(3, "case 5 and 6\n");
/*
* We have to postpone the callback due to the fact we
* will have a Lock Order Reversal, LOR, if we try to
- * proceed !
+ * proceed!
+ *
+ * Postponing the callback also ensures that other USB
+ * transfer queues get a chance.
*/
- if (usb_proc_msignal(info->done_p,
- &info->done_m[0], &info->done_m[1])) {
- /* ignore */
- }
+ (void) usb_proc_msignal(info->done_p,
+ &info->done_m[0], &info->done_m[1]);
return;
}
/*
@@ -2381,8 +2398,11 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq)
}
#if USB_HAVE_PF
- if (xfer->usb_state != USB_ST_SETUP)
+ if (xfer->usb_state != USB_ST_SETUP) {
+ USB_BUS_LOCK(info->bus);
usbpf_xfertap(xfer, USBPF_XFERTAP_DONE);
+ USB_BUS_UNLOCK(info->bus);
+ }
#endif
/* call processing routine */
(xfer->callback) (xfer, xfer->error);
@@ -2694,7 +2714,7 @@ usbd_pipe_start(struct usb_xfer_queue *pq)
} else if (udev->ctrl_xfer[1]) {
info = udev->ctrl_xfer[1]->xroot;
usb_proc_msignal(
- USB_BUS_NON_GIANT_PROC(info->bus),
+ USB_BUS_CS_PROC(info->bus),
&udev->cs_msg[0], &udev->cs_msg[1]);
} else {
/* should not happen */
@@ -3019,9 +3039,11 @@ usb_command_wrapper(struct usb_xfer_queue *pq, struct usb_xfer *xfer)
if (!pq->recurse_1) {
- do {
+ /* clear third recurse flag */
+ pq->recurse_3 = 0;
- /* set both recurse flags */
+ do {
+ /* set two first recurse flags */
pq->recurse_1 = 1;
pq->recurse_2 = 1;
@@ -3040,6 +3062,12 @@ usb_command_wrapper(struct usb_xfer_queue *pq, struct usb_xfer *xfer)
(pq->command) (pq);
DPRINTFN(6, "cb %p (leave)\n", pq->curr);
+ /*
+ * Set third recurse flag to indicate
+ * recursion happened:
+ */
+ pq->recurse_3 = 1;
+
} while (!pq->recurse_2);
/* clear first recurse flag */
@@ -3315,7 +3343,8 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
USB_BUS_CONTROL_XFER_PROC(udev->bus)->up_msleep = 0;
USB_BUS_EXPLORE_PROC(udev->bus)->up_msleep = 0;
USB_BUS_GIANT_PROC(udev->bus)->up_msleep = 0;
- USB_BUS_NON_GIANT_PROC(udev->bus)->up_msleep = 0;
+ USB_BUS_NON_GIANT_ISOC_PROC(udev->bus)->up_msleep = 0;
+ USB_BUS_NON_GIANT_BULK_PROC(udev->bus)->up_msleep = 0;
/* poll USB hardware */
(udev->bus->methods->xfer_poll) (udev->bus);
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index e4dfd37..04cfd54 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -4009,8 +4009,7 @@ product SIERRA C22 0x6891 C22
product SIERRA E6892 0x6892 E6892
product SIERRA E6893 0x6893 E6893
product SIERRA MC8700 0x68A3 MC8700
-product SIERRA MC7354 0x6820 MC7354
-product SIERRA AIRCARD875 0x6820 Aircard 875 HSDPA
+product SIERRA MC7354 0x68C0 MC7354
product SIERRA AC313U 0x68aa Sierra Wireless AirCard 313U
product SIERRA TRUINSTALL 0x0fff Aircard Tru Installer
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index f3930ff..a125184 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -128,6 +128,8 @@ struct usb_xfer_queue {
void (*command) (struct usb_xfer_queue *pq);
uint8_t recurse_1:1;
uint8_t recurse_2:1;
+ uint8_t recurse_3:1;
+ uint8_t reserved:5;
};
/*
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c
index 7f58cd9..c6d9448 100644
--- a/sys/fs/nfsserver/nfs_nfsdstate.c
+++ b/sys/fs/nfsserver/nfs_nfsdstate.c
@@ -406,9 +406,12 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
}
/* For NFSv4.1, mark that we found a confirmed clientid. */
- if ((nd->nd_flag & ND_NFSV41) != 0)
+ if ((nd->nd_flag & ND_NFSV41) != 0) {
+ clientidp->lval[0] = clp->lc_clientid.lval[0];
+ clientidp->lval[1] = clp->lc_clientid.lval[1];
+ confirmp->lval[0] = 0; /* Ignored by client */
confirmp->lval[1] = 1;
- else {
+ } else {
/*
* id and verifier match, so update the net address info
* and get rid of any existing callback authentication
diff --git a/sys/fs/procfs/procfs_ctl.c b/sys/fs/procfs/procfs_ctl.c
index 5a32863..15679e3 100644
--- a/sys/fs/procfs/procfs_ctl.c
+++ b/sys/fs/procfs/procfs_ctl.c
@@ -143,8 +143,8 @@ procfs_control(struct thread *td, struct proc *p, int op)
p->p_flag |= P_TRACED;
faultin(p);
p->p_xstat = 0; /* XXX ? */
+ p->p_oppid = p->p_pptr->p_pid;
if (p->p_pptr != td->td_proc) {
- p->p_oppid = p->p_pptr->p_pid;
proc_reparent(p, td->td_proc);
}
kern_psignal(p, SIGSTOP);
diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c
index e72e709..f1edc70 100644
--- a/sys/geom/geom_io.c
+++ b/sys/geom/geom_io.c
@@ -71,7 +71,17 @@ static struct g_bioq g_bio_run_down;
static struct g_bioq g_bio_run_up;
static struct g_bioq g_bio_run_task;
-static u_int pace;
+/*
+ * Pace is a hint that we've had some trouble recently allocating
+ * bios, so we should back off trying to send I/O down the stack
+ * a bit to let the problem resolve. When pacing, we also turn
+ * off direct dispatch to also reduce memory pressure from I/Os
+ * there, at the expxense of some added latency while the memory
+ * pressures exist. See g_io_schedule_down() for more details
+ * and limitations.
+ */
+static volatile u_int pace;
+
static uma_zone_t biozone;
/*
@@ -521,7 +531,8 @@ g_io_request(struct bio *bp, struct g_consumer *cp)
(pp->flags & G_PF_DIRECT_RECEIVE) != 0 &&
!g_is_geom_thread(curthread) &&
((pp->flags & G_PF_ACCEPT_UNMAPPED) != 0 ||
- (bp->bio_flags & BIO_UNMAPPED) == 0 || THREAD_CAN_SLEEP());
+ (bp->bio_flags & BIO_UNMAPPED) == 0 || THREAD_CAN_SLEEP()) &&
+ pace == 0;
if (direct) {
/* Block direct execution if less then half of stack left. */
size_t st, su;
@@ -688,7 +699,7 @@ g_io_deliver(struct bio *bp, int error)
bp->bio_driver2 = NULL;
bp->bio_pflags = 0;
g_io_request(bp, cp);
- pace++;
+ pace = 1;
return;
}
@@ -777,10 +788,33 @@ g_io_schedule_down(struct thread *tp __unused)
}
CTR0(KTR_GEOM, "g_down has work to do");
g_bioq_unlock(&g_bio_run_down);
- if (pace > 0) {
- CTR1(KTR_GEOM, "g_down pacing self (pace %d)", pace);
- pause("g_down", hz/10);
- pace--;
+ if (pace != 0) {
+ /*
+ * There has been at least one memory allocation
+ * failure since the last I/O completed. Pause 1ms to
+ * give the system a chance to free up memory. We only
+ * do this once because a large number of allocations
+ * can fail in the direct dispatch case and there's no
+ * relationship between the number of these failures and
+ * the length of the outage. If there's still an outage,
+ * we'll pause again and again until it's
+ * resolved. Older versions paused longer and once per
+ * allocation failure. This was OK for a single threaded
+ * g_down, but with direct dispatch would lead to max of
+ * 10 IOPs for minutes at a time when transient memory
+ * issues prevented allocation for a batch of requests
+ * from the upper layers.
+ *
+ * XXX This pacing is really lame. It needs to be solved
+ * by other methods. This is OK only because the worst
+ * case scenario is so rare. In the worst case scenario
+ * all memory is tied up waiting for I/O to complete
+ * which can never happen since we can't allocate bios
+ * for that I/O.
+ */
+ CTR0(KTR_GEOM, "g_down pacing self");
+ pause("g_down", min(hz/1000, 1));
+ pace = 0;
}
CTR2(KTR_GEOM, "g_down processing bp %p provider %s", bp,
bp->bio_to->name);
diff --git a/sys/gnu/fs/reiserfs/reiserfs_vfsops.c b/sys/gnu/fs/reiserfs/reiserfs_vfsops.c
index 496a6ad..ad2aab0 100644
--- a/sys/gnu/fs/reiserfs/reiserfs_vfsops.c
+++ b/sys/gnu/fs/reiserfs/reiserfs_vfsops.c
@@ -960,8 +960,8 @@ uint32_t find_hash_out(struct reiserfs_mount *rmp)
key.on_disk_key.k_objectid, key.on_disk_key.k_dir_id);
retval = search_by_entry_key(sbi, &key, &path, &de);
if (retval == IO_ERROR) {
- pathrelse(&path);
- return (UNSET_HASH);
+ hash = UNSET_HASH;
+ break;
}
if (retval == NAME_NOT_FOUND)
de.de_entry_num--;
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index a7b0526..23b4a6d 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -115,6 +115,10 @@ int bootverbose = BOOTVERBOSE;
SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0,
"Control the output of verbose kernel messages");
+#ifdef INVARIANTS
+FEATURE(invariants, "Kernel compiled with INVARIANTS, may affect performance");
+#endif
+
/*
* This ensures that there is at least one entry so that the sysinit_set
* symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index d4ed909..8846ae4 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -857,13 +857,13 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options)
PROC_LOCK(q);
sigqueue_take(p->p_ksi);
PROC_UNLOCK(q);
- PROC_UNLOCK(p);
/*
* If we got the child via a ptrace 'attach', we need to give it back
* to the old parent.
*/
- if (p->p_oppid != 0) {
+ if (p->p_oppid != 0 && p->p_oppid != p->p_pptr->p_pid) {
+ PROC_UNLOCK(p);
t = proc_realparent(p);
PROC_LOCK(t);
PROC_LOCK(p);
@@ -880,6 +880,8 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options)
sx_xunlock(&proctree_lock);
return;
}
+ p->p_oppid = 0;
+ PROC_UNLOCK(p);
/*
* Remove other references to this process to ensure we have an
@@ -962,7 +964,8 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options)
static int
proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id,
- int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo)
+ int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo,
+ int check_only)
{
struct rusage *rup;
@@ -1098,7 +1101,7 @@ proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id,
calccru(p, &rup->ru_utime, &rup->ru_stime);
}
- if (p->p_state == PRS_ZOMBIE) {
+ if (p->p_state == PRS_ZOMBIE && !check_only) {
proc_reap(td, p, status, options);
return (-1);
}
@@ -1192,7 +1195,7 @@ loop:
sx_xlock(&proctree_lock);
LIST_FOREACH(p, &q->p_children, p_sibling) {
ret = proc_to_reap(td, p, idtype, id, status, options,
- wrusage, siginfo);
+ wrusage, siginfo, 0);
if (ret == 0)
continue;
else if (ret == 1)
@@ -1294,15 +1297,17 @@ loop:
* for. By maintaining a list of orphans we allow the parent
* to successfully wait until the child becomes a zombie.
*/
- LIST_FOREACH(p, &q->p_orphans, p_orphan) {
- ret = proc_to_reap(td, p, idtype, id, status, options,
- wrusage, siginfo);
- if (ret == 0)
- continue;
- else if (ret == 1)
- nfound++;
- else
- return (0);
+ if (nfound == 0) {
+ LIST_FOREACH(p, &q->p_orphans, p_orphan) {
+ ret = proc_to_reap(td, p, idtype, id, NULL, options,
+ NULL, NULL, 1);
+ if (ret != 0) {
+ KASSERT(ret != -1, ("reaped an orphan (pid %d)",
+ (int)td->td_retval[0]));
+ nfound++;
+ break;
+ }
+ }
}
if (nfound == 0) {
sx_xunlock(&proctree_lock);
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index 155d1f9..9f23558 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -1001,7 +1001,7 @@ callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t precision,
* currently in progress. If there is a lock then we
* can cancel the callout if it has not really started.
*/
- if (c->c_lock != NULL && cc_exec_cancel(cc, direct))
+ if (c->c_lock != NULL && !cc_exec_cancel(cc, direct))
cancelled = cc_exec_cancel(cc, direct) = true;
if (cc_exec_waiting(cc, direct)) {
/*
diff --git a/sys/kern/ksched.c b/sys/kern/ksched.c
index efb673e..27aea72 100644
--- a/sys/kern/ksched.c
+++ b/sys/kern/ksched.c
@@ -30,8 +30,7 @@
* SUCH DAMAGE.
*/
-/* ksched: Soft real time scheduling based on "rtprio".
- */
+/* ksched: Soft real time scheduling based on "rtprio". */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -51,8 +50,7 @@ __FBSDID("$FreeBSD$");
FEATURE(kposix_priority_scheduling, "POSIX P1003.1B realtime extensions");
-/* ksched: Real-time extension to support POSIX priority scheduling.
- */
+/* ksched: Real-time extension to support POSIX priority scheduling. */
struct ksched {
struct timespec rr_interval;
@@ -61,21 +59,21 @@ struct ksched {
int
ksched_attach(struct ksched **p)
{
- struct ksched *ksched= p31b_malloc(sizeof(*ksched));
+ struct ksched *ksched;
+ ksched = malloc(sizeof(*ksched), M_P31B, M_WAITOK);
ksched->rr_interval.tv_sec = 0;
ksched->rr_interval.tv_nsec = 1000000000L / hz * sched_rr_interval();
-
*p = ksched;
- return 0;
+ return (0);
}
int
ksched_detach(struct ksched *ks)
{
- p31b_free(ks);
- return 0;
+ free(ks, M_P31B);
+ return (0);
}
/*
@@ -108,47 +106,39 @@ static __inline int
getscheduler(struct ksched *ksched, struct thread *td, int *policy)
{
struct rtprio rtp;
- int e = 0;
+ int e;
+ e = 0;
pri_to_rtp(td, &rtp);
- switch (rtp.type)
- {
- case RTP_PRIO_FIFO:
+ switch (rtp.type) {
+ case RTP_PRIO_FIFO:
*policy = SCHED_FIFO;
break;
-
- case RTP_PRIO_REALTIME:
+ case RTP_PRIO_REALTIME:
*policy = SCHED_RR;
break;
-
- default:
+ default:
*policy = SCHED_OTHER;
break;
}
-
- return e;
+ return (e);
}
int
ksched_setparam(struct ksched *ksched,
struct thread *td, const struct sched_param *param)
{
- int policy;
- int e;
+ int e, policy;
e = getscheduler(ksched, td, &policy);
-
if (e == 0)
- {
- e = ksched_setscheduler(ksched, td, policy, param);
- }
-
- return e;
+ e = ksched_setscheduler(ksched, td, policy, param);
+ return (e);
}
int
-ksched_getparam(struct ksched *ksched,
- struct thread *td, struct sched_param *param)
+ksched_getparam(struct ksched *ksched, struct thread *td,
+ struct sched_param *param)
{
struct rtprio rtp;
@@ -159,13 +149,14 @@ ksched_getparam(struct ksched *ksched,
if (PRI_MIN_TIMESHARE < rtp.prio)
/*
* The interactive score has it to min realtime
- * so we must show max (64 most likely
+ * so we must show max (64 most likely).
*/
- param->sched_priority = (PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE);
+ param->sched_priority = PRI_MAX_TIMESHARE -
+ PRI_MIN_TIMESHARE;
else
param->sched_priority = tsprio_to_p4prio(rtp.prio);
}
- return 0;
+ return (0);
}
/*
@@ -176,117 +167,106 @@ ksched_getparam(struct ksched *ksched,
*
*/
int
-ksched_setscheduler(struct ksched *ksched,
- struct thread *td, int policy, const struct sched_param *param)
+ksched_setscheduler(struct ksched *ksched, struct thread *td, int policy,
+ const struct sched_param *param)
{
- int e = 0;
struct rtprio rtp;
+ int e;
- switch(policy)
- {
- case SCHED_RR:
- case SCHED_FIFO:
-
+ e = 0;
+ switch(policy) {
+ case SCHED_RR:
+ case SCHED_FIFO:
if (param->sched_priority >= P1B_PRIO_MIN &&
- param->sched_priority <= P1B_PRIO_MAX)
- {
+ param->sched_priority <= P1B_PRIO_MAX) {
rtp.prio = p4prio_to_rtpprio(param->sched_priority);
- rtp.type = (policy == SCHED_FIFO)
- ? RTP_PRIO_FIFO : RTP_PRIO_REALTIME;
-
+ rtp.type = (policy == SCHED_FIFO) ? RTP_PRIO_FIFO :
+ RTP_PRIO_REALTIME;
rtp_to_pri(&rtp, td);
- }
- else
+ } else {
e = EPERM;
-
-
+ }
break;
-
- case SCHED_OTHER:
- if (param->sched_priority >= 0 &&
- param->sched_priority <= (PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE)) {
+ case SCHED_OTHER:
+ if (param->sched_priority >= 0 && param->sched_priority <=
+ (PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE)) {
rtp.type = RTP_PRIO_NORMAL;
rtp.prio = p4prio_to_tsprio(param->sched_priority);
rtp_to_pri(&rtp, td);
- } else
+ } else {
e = EINVAL;
-
+ }
+ break;
+ default:
+ e = EINVAL;
break;
-
- default:
- e = EINVAL;
- break;
}
-
- return e;
+ return (e);
}
int
ksched_getscheduler(struct ksched *ksched, struct thread *td, int *policy)
{
- return getscheduler(ksched, td, policy);
+
+ return (getscheduler(ksched, td, policy));
}
-/* ksched_yield: Yield the CPU.
- */
+/* ksched_yield: Yield the CPU. */
int
ksched_yield(struct ksched *ksched)
{
+
sched_relinquish(curthread);
- return 0;
+ return (0);
}
int
ksched_get_priority_max(struct ksched *ksched, int policy, int *prio)
{
- int e = 0;
+ int e;
- switch (policy)
- {
- case SCHED_FIFO:
- case SCHED_RR:
- *prio = RTP_PRIO_MAX;
+ e = 0;
+ switch (policy) {
+ case SCHED_FIFO:
+ case SCHED_RR:
+ *prio = P1B_PRIO_MAX;
break;
-
- case SCHED_OTHER:
+ case SCHED_OTHER:
*prio = PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE;
break;
-
- default:
+ default:
e = EINVAL;
+ break;
}
-
- return e;
+ return (e);
}
int
ksched_get_priority_min(struct ksched *ksched, int policy, int *prio)
{
- int e = 0;
+ int e;
- switch (policy)
- {
- case SCHED_FIFO:
- case SCHED_RR:
+ e = 0;
+ switch (policy) {
+ case SCHED_FIFO:
+ case SCHED_RR:
*prio = P1B_PRIO_MIN;
break;
-
- case SCHED_OTHER:
+ case SCHED_OTHER:
*prio = 0;
break;
-
- default:
+ default:
e = EINVAL;
+ break;
}
-
- return e;
+ return (e);
}
int
-ksched_rr_get_interval(struct ksched *ksched,
- struct thread *td, struct timespec *timespec)
+ksched_rr_get_interval(struct ksched *ksched, struct thread *td,
+ struct timespec *timespec)
{
- *timespec = ksched->rr_interval;
- return 0;
+ *timespec = ksched->rr_interval;
+ return (0);
}
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 122a246..bd54f57 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -1221,7 +1221,7 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
for (j = 0, lle = lock_list; lle != NULL; lle = lle->ll_next) {
for (i = lle->ll_count - 1; i >= 0; i--, j++) {
- MPASS(j < WITNESS_COUNT);
+ MPASS(j < LOCK_CHILDCOUNT * LOCK_NCHILDREN);
lock1 = &lle->ll_children[i];
/*
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 09a43f4..6ad4694 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -946,7 +946,15 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
}
break;
case PT_DETACH:
- /* reset process parent */
+ /*
+ * Reset the process parent.
+ *
+ * NB: This clears P_TRACED before reparenting
+ * a detached process back to its original
+ * parent. Otherwise the debugee will be set
+ * as an orphan of the debugger.
+ */
+ p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
if (p->p_oppid != p->p_pptr->p_pid) {
PROC_LOCK(p->p_pptr);
sigqueue_take(p->p_ksi);
@@ -962,7 +970,6 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
} else
CTR1(KTR_PTRACE, "PT_DETACH: pid %d", p->p_pid);
p->p_oppid = 0;
- p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
p->p_stops = 0;
/* should we send SIGCHLD? */
diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c
index 42a8a7a..540f06c 100644
--- a/sys/net/if_epair.c
+++ b/sys/net/if_epair.c
@@ -100,7 +100,7 @@ static int epair_clone_destroy(struct if_clone *, struct ifnet *);
static const char epairname[] = "epair";
-/* Netisr realted definitions and sysctl. */
+/* Netisr related definitions and sysctl. */
static struct netisr_handler epair_nh = {
.nh_name = epairname,
.nh_proto = NETISR_EPAIR,
@@ -171,7 +171,8 @@ STAILQ_HEAD(eid_list, epair_ifp_drain);
static MALLOC_DEFINE(M_EPAIR, epairname,
"Pair of virtual cross-over connected Ethernet-like interfaces");
-static struct if_clone *epair_cloner;
+static VNET_DEFINE(struct if_clone *, epair_cloner);
+#define V_epair_cloner VNET(epair_cloner)
/*
* DPCPU area and functions.
@@ -759,10 +760,17 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifc_free_unit(ifc, unit);
return (ENOSPC);
}
- *dp = 'a';
+ *dp = 'b';
/* Must not change dp so we can replace 'a' by 'b' later. */
*(dp+1) = '\0';
+ /* Check if 'a' and 'b' interfaces already exist. */
+ if (ifunit(name) != NULL)
+ return (EEXIST);
+ *dp = 'a';
+ if (ifunit(name) != NULL)
+ return (EEXIST);
+
/* Allocate memory for both [ab] interfaces */
sca = malloc(sizeof(struct epair_softc), M_EPAIR, M_WAITOK | M_ZERO);
EPAIR_REFCOUNT_INIT(&sca->refcount, 1);
@@ -800,6 +808,14 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
netisr_get_cpuid(sca->ifp->if_index % netisr_get_cpucount());
scb->cpuid =
netisr_get_cpuid(scb->ifp->if_index % netisr_get_cpucount());
+
+ /* Initialise pseudo media types. */
+ ifmedia_init(&sca->media, 0, epair_media_change, epair_media_status);
+ ifmedia_add(&sca->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+ ifmedia_set(&sca->media, IFM_ETHER | IFM_10G_T);
+ ifmedia_init(&scb->media, 0, epair_media_change, epair_media_status);
+ ifmedia_add(&scb->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+ ifmedia_set(&scb->media, IFM_ETHER | IFM_10G_T);
/* Finish initialization of interface <n>a. */
ifp = sca->ifp;
@@ -858,14 +874,6 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
strlcpy(name, sca->ifp->if_xname, len);
DPRINTF("name='%s/%db' created sca=%p scb=%p\n", name, unit, sca, scb);
- /* Initialise pseudo media types. */
- ifmedia_init(&sca->media, 0, epair_media_change, epair_media_status);
- ifmedia_add(&sca->media, IFM_ETHER | IFM_10G_T, 0, NULL);
- ifmedia_set(&sca->media, IFM_ETHER | IFM_10G_T);
- ifmedia_init(&scb->media, 0, epair_media_change, epair_media_status);
- ifmedia_add(&scb->media, IFM_ETHER | IFM_10G_T, 0, NULL);
- ifmedia_set(&scb->media, IFM_ETHER | IFM_10G_T);
-
/* Tell the world, that we are ready to rock. */
sca->ifp->if_drv_flags |= IFF_DRV_RUNNING;
scb->ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -943,6 +951,25 @@ epair_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
return (0);
}
+static void
+vnet_epair_init(const void *unused __unused)
+{
+
+ V_epair_cloner = if_clone_advanced(epairname, 0,
+ epair_clone_match, epair_clone_create, epair_clone_destroy);
+}
+VNET_SYSINIT(vnet_epair_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_epair_init, NULL);
+
+static void
+vnet_epair_uninit(const void *unused __unused)
+{
+
+ if_clone_detach(V_epair_cloner);
+}
+VNET_SYSUNINIT(vnet_epair_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_epair_uninit, NULL);
+
static int
epair_modevent(module_t mod, int type, void *data)
{
@@ -956,13 +983,10 @@ epair_modevent(module_t mod, int type, void *data)
if (TUNABLE_INT_FETCH("net.link.epair.netisr_maxqlen", &qlimit))
epair_nh.nh_qlimit = qlimit;
netisr_register(&epair_nh);
- epair_cloner = if_clone_advanced(epairname, 0,
- epair_clone_match, epair_clone_create, epair_clone_destroy);
if (bootverbose)
printf("%s initialized.\n", epairname);
break;
case MOD_UNLOAD:
- if_clone_detach(epair_cloner);
netisr_unregister(&epair_nh);
epair_dpcpu_detach();
if (bootverbose)
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index be603b7..4a809c8 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -6653,7 +6653,17 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
M_ASSERTPKTHDR(m);
- if (dir == PF_OUT && m->m_pkthdr.rcvif && ifp != m->m_pkthdr.rcvif)
+ /* Detect packet forwarding.
+ * If the input interface is different from the output interface we're
+ * forwarding.
+ * We do need to be careful about bridges. If the
+ * net.link.bridge.pfil_bridge sysctl is set we can be filtering on a
+ * bridge, so if the input interface is a bridge member and the output
+ * interface is its bridge we're not actually forwarding but bridging.
+ */
+ if (dir == PF_OUT && m->m_pkthdr.rcvif && ifp != m->m_pkthdr.rcvif
+ && (m->m_pkthdr.rcvif->if_bridge == NULL
+ || m->m_pkthdr.rcvif->if_bridge != ifp->if_softc))
fwdir = PF_FWD;
if (!V_pf_status.running)
diff --git a/sys/ofed/include/linux/in.h b/sys/ofed/include/linux/in.h
index d3e8add..102563f 100644
--- a/sys/ofed/include/linux/in.h
+++ b/sys/ofed/include/linux/in.h
@@ -37,7 +37,7 @@
#include <netinet/in.h>
#include <asm/byteorder.h>
-#define ipv4_is_zeronet IN_ZERONET
-#define ipv4_is_loopback IN_LOOPBACK
+#define ipv4_is_zeronet(be) IN_ZERONET(ntohl(be))
+#define ipv4_is_loopback(be) IN_LOOPBACK(ntohl(be))
#endif /* _LINUX_IN_H_ */
diff --git a/sys/ofed/include/linux/linux_compat.c b/sys/ofed/include/linux/linux_compat.c
index f428fc8..e9cc0c6 100644
--- a/sys/ofed/include/linux/linux_compat.c
+++ b/sys/ofed/include/linux/linux_compat.c
@@ -33,6 +33,7 @@
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
+#include <sys/sglist.h>
#include <sys/sleepqueue.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -414,16 +415,6 @@ linux_dev_poll(struct cdev *dev, int events, struct thread *td)
}
static int
-linux_dev_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
- int nprot, vm_memattr_t *memattr)
-{
-
- /* XXX memattr not honored. */
- *paddr = offset;
- return (0);
-}
-
-static int
linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
vm_size_t size, struct vm_object **object, int nprot)
{
@@ -431,36 +422,41 @@ linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
struct linux_file *filp;
struct file *file;
struct vm_area_struct vma;
- vm_paddr_t paddr;
- vm_page_t m;
int error;
file = curthread->td_fpop;
ldev = dev->si_drv1;
if (ldev == NULL)
return (ENODEV);
- if (size != PAGE_SIZE)
- return (EINVAL);
if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
return (error);
filp->f_flags = file->f_flag;
vma.vm_start = 0;
- vma.vm_end = PAGE_SIZE;
+ vma.vm_end = size;
vma.vm_pgoff = *offset / PAGE_SIZE;
vma.vm_pfn = 0;
vma.vm_page_prot = 0;
if (filp->f_op->mmap) {
error = -filp->f_op->mmap(filp, &vma);
if (error == 0) {
- paddr = (vm_paddr_t)vma.vm_pfn << PAGE_SHIFT;
- *offset = paddr;
- m = PHYS_TO_VM_PAGE(paddr);
- *object = vm_pager_allocate(OBJT_DEVICE, dev,
- PAGE_SIZE, nprot, *offset, curthread->td_ucred);
- if (*object == NULL)
- return (EINVAL);
- if (vma.vm_page_prot != VM_MEMATTR_DEFAULT)
- pmap_page_set_memattr(m, vma.vm_page_prot);
+ struct sglist *sg;
+
+ sg = sglist_alloc(1, M_WAITOK);
+ sglist_append_phys(sg,
+ (vm_paddr_t)vma.vm_pfn << PAGE_SHIFT, vma.vm_len);
+ *object = vm_pager_allocate(OBJT_SG, sg, vma.vm_len,
+ nprot, 0, curthread->td_ucred);
+ if (*object == NULL) {
+ sglist_free(sg);
+ return (EINVAL);
+ }
+ *offset = 0;
+ if (vma.vm_page_prot != VM_MEMATTR_DEFAULT) {
+ VM_OBJECT_WLOCK(*object);
+ vm_object_set_memattr(*object,
+ vma.vm_page_prot);
+ VM_OBJECT_WUNLOCK(*object);
+ }
}
} else
error = ENODEV;
@@ -477,7 +473,6 @@ struct cdevsw linuxcdevsw = {
.d_write = linux_dev_write,
.d_ioctl = linux_dev_ioctl,
.d_mmap_single = linux_dev_mmap_single,
- .d_mmap = linux_dev_mmap,
.d_poll = linux_dev_poll,
};
diff --git a/sys/ofed/include/linux/mm.h b/sys/ofed/include/linux/mm.h
index 80d59e8..b1a575c 100644
--- a/sys/ofed/include/linux/mm.h
+++ b/sys/ofed/include/linux/mm.h
@@ -40,6 +40,7 @@ struct vm_area_struct {
vm_offset_t vm_end;
vm_offset_t vm_pgoff;
vm_paddr_t vm_pfn; /* PFN For mmap. */
+ vm_size_t vm_len; /* length for mmap. */
vm_memattr_t vm_page_prot;
};
@@ -78,6 +79,7 @@ io_remap_pfn_range(struct vm_area_struct *vma,
{
vma->vm_page_prot = prot;
vma->vm_pfn = pfn;
+ vma->vm_len = size;
return (0);
}
diff --git a/sys/rpc/rpc_generic.c b/sys/rpc/rpc_generic.c
index 4643bf5..28aa849 100644
--- a/sys/rpc/rpc_generic.c
+++ b/sys/rpc/rpc_generic.c
@@ -703,7 +703,9 @@ __rpc_sockisbound(struct socket *so)
struct sockaddr *sa;
int error, bound;
+ CURVNET_SET(so->so_vnet);
error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
+ CURVNET_RESTORE();
if (error)
return (0);
@@ -791,7 +793,9 @@ bindresvport(struct socket *so, struct sockaddr *sa)
socklen_t salen;
if (sa == NULL) {
+ CURVNET_SET(so->so_vnet);
error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
+ CURVNET_RESTORE();
if (error)
return (error);
freesa = TRUE;
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c
index fb40a34..be8e04e 100644
--- a/sys/rpc/svc_vc.c
+++ b/sys/rpc/svc_vc.c
@@ -150,7 +150,9 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
SOCK_LOCK(so);
if (so->so_state & (SS_ISCONNECTED|SS_ISDISCONNECTED)) {
SOCK_UNLOCK(so);
+ CURVNET_SET(so->so_vnet);
error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
+ CURVNET_RESTORE();
if (error)
return (NULL);
xprt = svc_vc_create_conn(pool, so, sa);
@@ -167,7 +169,9 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
xprt->xp_p2 = NULL;
xprt->xp_ops = &svc_vc_rendezvous_ops;
+ CURVNET_SET(so->so_vnet);
error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
+ CURVNET_RESTORE();
if (error) {
goto cleanup_svc_vc_create;
}
@@ -249,7 +253,9 @@ svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr)
memcpy(&xprt->xp_rtaddr, raddr, raddr->sa_len);
+ CURVNET_SET(so->so_vnet);
error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
+ CURVNET_RESTORE();
if (error)
goto cleanup_svc_vc_create;
diff --git a/sys/sys/posix4.h b/sys/sys/posix4.h
index 25dbeae..8dcf36d 100644
--- a/sys/sys/posix4.h
+++ b/sys/sys/posix4.h
@@ -56,9 +56,6 @@ int sys_ ## SC (struct thread *td, struct SC##_args *uap) \
MALLOC_DECLARE(M_P31B);
-#define p31b_malloc(SIZE) malloc((SIZE), M_P31B, M_WAITOK)
-#define p31b_free(P) free((P), M_P31B)
-
int p31b_proc(struct proc *, pid_t, struct proc **);
void p31b_setcfg(int, int);
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 9090340..0afafc5 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -76,7 +76,7 @@ struct socket {
short so_state; /* (b) internal state flags SS_* */
int so_qstate; /* (e) internal state flags SQ_* */
void *so_pcb; /* protocol control block */
- struct vnet *so_vnet; /* network stack instance */
+ struct vnet *so_vnet; /* (a) network stack instance */
struct protosw *so_proto; /* (a) protocol handle */
/*
* Variables for connection queuing.
diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h
index 8148f14..1de4f1f 100644
--- a/sys/x86/include/specialreg.h
+++ b/sys/x86/include/specialreg.h
@@ -157,6 +157,7 @@
#define CPUID2_TM2 0x00000100
#define CPUID2_SSSE3 0x00000200
#define CPUID2_CNXTID 0x00000400
+#define CPUID2_SDBG 0x00000800
#define CPUID2_FMA 0x00001000
#define CPUID2_CX16 0x00002000
#define CPUID2_XTPR 0x00004000
diff --git a/sys/x86/x86/identcpu.c b/sys/x86/x86/identcpu.c
index 8e5f5c3..1804595 100644
--- a/sys/x86/x86/identcpu.c
+++ b/sys/x86/x86/identcpu.c
@@ -781,7 +781,7 @@ printcpuinfo(void)
"\011TM2" /* Thermal Monitor 2 */
"\012SSSE3" /* SSSE3 */
"\013CNXT-ID" /* L1 context ID available */
- "\014<b11>"
+ "\014SDBG" /* IA32 silicon debug */
"\015FMA" /* Fused Multiply Add */
"\016CX16" /* CMPXCHG16B Instruction */
"\017xTPR" /* Send Task Priority Messages*/
OpenPOWER on IntegriCloud