Page MenuHomeFreeBSD

D56985.id.diff
No OneTemporary

D56985.id.diff

diff --git a/sys/dev/usb/net/usb_ethernet.h b/sys/dev/usb/net/usb_ethernet.h
--- a/sys/dev/usb/net/usb_ethernet.h
+++ b/sys/dev/usb/net/usb_ethernet.h
@@ -81,6 +81,8 @@
struct usb_device *ue_udev; /* used by uether_do_request() */
device_t ue_dev;
device_t ue_miibus;
+ struct cv ioctl_cv;
+ int pending_ioctl;
struct usb_process ue_tq;
struct sysctl_ctx_list ue_sysctl_ctx;
diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c
--- a/sys/dev/usb/net/usb_ethernet.c
+++ b/sys/dev/usb/net/usb_ethernet.c
@@ -175,6 +175,9 @@
goto error;
}
+ ue->pending_ioctl = 0;
+ cv_init(&ue->ioctl_cv, "uether_ioctl_cv");
+
/* fork rest of the attach code */
UE_LOCK(ue);
ue_queue_command(ue, ue_attach_post_task,
@@ -319,6 +322,8 @@
bus_generic_detach(ue->ue_dev);
bus_topo_unlock();
+ cv_destroy(&ue->ioctl_cv);
+
/* free interface instance */
if_free(ifp);
@@ -535,8 +540,27 @@
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
if (ue->ue_miibus != NULL) {
+ UE_LOCK(ue);
+ /* There are pending ioctl */
+ if (ue->pending_ioctl)
+ cv_wait(&ue->ioctl_cv, ue->ue_mtx);
+ /* No pending ioctl, stop ue_tick to avoid race condition */
+ else if (ue->ue_methods->ue_tick != NULL)
+ usb_callout_stop(&ue->ue_watchdog);
+ ue->pending_ioctl++;
+ UE_UNLOCK(ue);
+
mii = device_get_softc(ue->ue_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+
+ UE_LOCK(ue);
+ ue->pending_ioctl--;
+ /* We are the last ioctl running, restore back the watchdog */
+ if (ue->pending_ioctl == 0 && ue->ue_methods->ue_tick != NULL)
+ usb_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue);
+ /* unblock one ioctl waiter */
+ cv_signal(&ue->ioctl_cv);
+ UE_UNLOCK(ue);
} else
error = ether_ioctl(ifp, command, data);
break;

File Metadata

Mime Type
text/plain
Expires
Wed, Jul 22, 6:50 PM (5 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33036661
Default Alt Text
D56985.id.diff (1 KB)

Event Timeline