PERFORCE change 131706 for review
Maxim Zhuravlev
thioretic at FreeBSD.org
Wed Dec 26 08:16:08 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=131706
Change 131706 by thioretic at thioretic on 2007/12/26 16:16:02
The event framework is now well outlined. It's not extensible yet.
Still, the extensibility is implied by design.
Affected files ...
.. //depot/projects/soc2007/thioretic_gidl2/kern/device_if.m#3 edit
.. //depot/projects/soc2007/thioretic_gidl2/kern/subr_bus.c#11 edit
.. //depot/projects/soc2007/thioretic_gidl2/sys/bus.h#7 edit
Differences ...
==== //depot/projects/soc2007/thioretic_gidl2/kern/device_if.m#3 (text+ko) ====
@@ -67,7 +67,7 @@
return NULL;
}
static void null_receive_event (device_t dev, device_t provider,
- enum relationship rel, enum dev_event ev)
+ int rel, uint32_t ev)
{
return;
}
@@ -375,6 +375,6 @@
METHOD void receive_event {
device_t dev;
device_t provider;
- enum relationship rel;
- enum dev_event ev_type;
+ int rel;
+ uint32_t ev_type;
} DEFAULT null_receive_event;
==== //depot/projects/soc2007/thioretic_gidl2/kern/subr_bus.c#11 (text+ko) ====
@@ -130,7 +130,7 @@
};
struct dev_event_entry {
- enum dev_event ev_type;
+ uint32_t ev_type;
TAILQ_ENTRY(dev_event_entry) link;
};
typedef struct dev_event_entry* dev_event_entry_t;
@@ -2069,24 +2069,42 @@
}
}
-static void device_issue_event (device_t dev, enum dev_event ev_type){
+static void device_issue_event (device_t dev, uint32_t ev_type){
dev_event_entry_t dee;
devicelink_t pd;
+ int dequeuedevents = 0;
+
+ if (ev_type > EV_MAX)
+ return;
/*deliver to all children*/
- if (!TAILQ_EMPTY(&dev->children)){
+ if ((event_pref[ev_type] & REL_CHILD) &&
+ !TAILQ_EMPTY(&dev->children)){
TAILQ_FOREACH (pd, &dev->children, link){
- DEVICE_RECEIVE_EVENT (pd, dev, REL_CHILD, ev_type);
+ DEVICE_RECEIVE_EVENT (pd, dev, REL_PARENT, ev_type);
}
}
/*deliver to all parents*/
- if (!TAILQ_EMPTY(&dev->parents)){
+ if ((event_pref[ev_type] & REL_PARENT) &&
+ !TAILQ_EMPTY(&dev->parents)){
TAILQ_FOREACH (pd, &dev->parents, link){
- DEVICE_RECEIVE_EVENT (pd, dev, REL_PARENT, ev_type);
+ DEVICE_RECEIVE_EVENT (pd, dev, REL_CHILD, ev_type);
}
}
+ while (!TAILQ_EMPTY(&dev->evs)){
+ dee = TAILQ_LAST(&dev->evs, dev_event_list);
+ if (!(event_pref[ev_type] & (1<<(dee->ev_type))))
+ break;
+ TAILQ_REMOVE(&dev->evs, dee, link);
+ free (dee);
+ dequeuedevents++;
+ }
+
+ if (dequeuedevents > 0 && !(event_pref[ev_type] & EVP_ENQALWAYS))
+ return;
+
/*enqueue*/
dee = malloc (sizeof(struct dev_event_entry), M_BUS, M_NOWAIT|M_ZERO);
if (dee == NULL)
@@ -2096,7 +2114,7 @@
TAILQ_INSERT_TAIL (&dev->evs, dee, link);
}
-static void device_deliver_events (device_t dev, device_t recipient, enum relationship rel){
+static void device_deliver_events (device_t dev, device_t recipient, int rel){
dev_event_entry_t dee;
if (TAILQ_EMPTY(&dev->evs))
@@ -3299,6 +3317,11 @@
if(driver == NULL || level == DRL_LOWEST){
if(!device_destroy_configuration(dev))
return (EBUSY);
+ while (!TAILQ_EMPTY(&dev->evs)){
+ dee = TAILQ_FIRST(&dev->evs);
+ TAILQ_REMOVE (&dev->evs, dee, link);
+ free (dee);
+ }
}
if (!dil){
@@ -3444,6 +3467,7 @@
dev->driver_level=DRL_LOWEST;
return (error);
}
+ device_issue_event(dev, EV_ATTACH);
dil = dev->driver;
if (dev->driver_level == DRL_LOWEST){
@@ -3481,6 +3505,7 @@
{
int error;
devicelink_t pd;
+ dev_event_entry_t dee;
GIANT_REQUIRED;
@@ -3492,6 +3517,7 @@
if ((error = DEVICE_DETACH(dev)) != 0)
return (error);
+
if (dev->driver_level != DRL_LOWEST){
TAILQ_REMOVE(&dev->drivers[dev->driver_level], dev->driver, link);
free(dev->driver);
@@ -3503,6 +3529,8 @@
dev->state = DS_ATTACHED;
return (0);
}
+ device_issue_event(dev, EV_DETACH);
+
devremoved(dev);
device_printf(dev, "detached\n");
if (!TAILQ_EMPTY(&dev->parents)){
@@ -3538,6 +3566,7 @@
int
device_quiesce(device_t dev)
{
+ int result;
PDEBUG(("%s", DEVICENAME(dev)));
if (dev->state == DS_BUSY)
@@ -3545,7 +3574,10 @@
if (dev->state != DS_ATTACHED)
return (0);
- return (DEVICE_QUIESCE(dev));
+ if (result = DEVICE_QUIESCE(dev))
+ device_issue_event(dev, EV_QUIESCE);
+
+ return (result);
}
/**
@@ -3559,9 +3591,14 @@
int
device_shutdown(device_t dev)
{
+ int result;
+
if (dev->state < DS_ATTACHED)
return (0);
- return (DEVICE_SHUTDOWN(dev));
+ result = DEVICE_SHUTDOWN(dev);
+ device_issue_event(dev, EV_SHUTDOWN);
+
+ return (result);
}
/**
@@ -4033,10 +4070,13 @@
if (error) {
for (child2 = TAILQ_FIRST(&dev->children);
child2 && child2 != child;
- child2 = TAILQ_NEXT(child2, link))
+ child2 = TAILQ_NEXT(child2, link)){
DEVICE_RESUME(child2);
+// device_issue_event(child2, EV_RESUME);
+ }
return (error);
}
+ device_issue_event(child, EV_SUSPEND);
}
return (0);
}
@@ -4053,7 +4093,8 @@
device_t child;
TAILQ_FOREACH(child, &dev->children, link) {
- DEVICE_RESUME(child);
+ if (DEVICE_RESUME(child))
+ device_issue_event(child, EV_RESUME);
/* if resume fails, there's nothing we can usefully do... */
}
return (0);
==== //depot/projects/soc2007/thioretic_gidl2/sys/bus.h#7 (text+ko) ====
@@ -713,21 +713,35 @@
bus_space_write_region_stream_8(rman_get_bustag(r), rman_get_bushandle(r), (o), (d), (c))
/**
- * Triggers support functions
+ * event support functions
+ */
+#define EV_ATTACH 0
+#define EV_DETACH 1
+#define EV_RESUME 2
+#define EV_SUSPEND 3
+#define EV_QUIESCE 4
+#define EV_SHUTDOWN 5
+
+#define EV_MAX 28
+
+#define REL_CHILD (1<<29)
+#define REL_PARENT (1<<30)
+#define EVP_ENQALWAYS (1<<31)
+/**
+ * event_pref array is an array of event settings.
+ * includes:
+ * what devices should receive the event (children and/or parents)
+ * what enqueued events should be dequeued
*/
-enum dev_event{
- EV_ATTACH,
- EV_DETACH,
- EV_RESUME,
- EV_SUSPEND,
- EV_QUIESCE,
- EV_SHUTDOWN
-};
-enum relationship {
- REL_CHILD,
- REL_PARENT
-};
+uint32_t event_pref[32] =
+ { REL_CHILD | REL_PARENT, /* EV_ATTACH */
+ REL_CHILD | REL_PARENT | (REL_CHILD - 1), /* EV_DETACH */
+ REL_CHILD | REL_PARENT | (1<<EV_SUSPEND), /* EV_RESUME */
+ REL_CHILD | REL_PARENT | (1<<EV_RESUME), /* EV_SUSPEND */
+ REL_CHILD | REL_PARENT, /* EV_QUIESCE */ /* TODO */
+ REL_CHILD | REL_PARENT, /* EV_SHUTDOWN */ /* TODO */
+ };
#endif /* _KERNEL */
More information about the p4-projects
mailing list