#include "visorbus.h"
#include "visorbus_private.h"
#include "version.h"
-#include "periodic_work.h"
-#include "vbuschannel.h"
-#include "guestlinuxdebug.h"
#include "vmcallinterface.h"
#define MYDRVNAME "visorbus"
/* module parameters */
-static int visorbus_debug;
static int visorbus_forcematch;
static int visorbus_forcenomatch;
-static int visorbus_debugref;
-#define SERIALLOOPBACKCHANADDR (100 * 1024 * 1024)
/* Display string that is guaranteed to be no longer the 99 characters*/
#define LINESIZE 99
#define CURRENT_FILE_PC VISOR_BUS_PC_visorbus_main_c
-#define POLLJIFFIES_TESTWORK 100
#define POLLJIFFIES_NORMALCHANNEL 10
static int busreg_rc = -ENODEV; /* stores the result from bus registration */
static int visorbus_match(struct device *xdev, struct device_driver *xdrv);
static void fix_vbus_dev_info(struct visor_device *visordev);
-/* BUS type attributes
- *
- * define & implement display of bus attributes under
- * /sys/bus/visorbus.
+/*
+ * BUS type attributes
*
+ * define & implement display of bus attributes under
+ * /sys/bus/visorbus.
*/
static ssize_t version_show(struct bus_type *bus, char *buf)
NULL,
};
-/** This describes the TYPE of bus.
+/*
+ * This describes the TYPE of bus.
* (Don't confuse this with an INSTANCE of the bus.)
*/
struct bus_type visorbus_type = {
.bus_groups = visorbus_bus_groups,
};
-static struct delayed_work periodic_work;
-
-/* YES, we need 2 workqueues.
- * The reason is, workitems on the test queue may need to cancel
- * workitems on the other queue. You will be in for trouble if you try to
- * do this with workitems queued on the same workqueue.
- */
-static struct workqueue_struct *periodic_test_workqueue;
-static struct workqueue_struct *periodic_dev_workqueue;
-static long long bus_count; /** number of bus instances */
- /** ever-increasing */
-
-static void chipset_bus_create(struct visor_device *bus_info);
-static void chipset_bus_destroy(struct visor_device *bus_info);
-static void chipset_device_create(struct visor_device *dev_info);
-static void chipset_device_destroy(struct visor_device *dev_info);
-static void chipset_device_pause(struct visor_device *dev_info);
-static void chipset_device_resume(struct visor_device *dev_info);
-
-/** These functions are implemented herein, and are called by the chipset
- * driver to notify us about specific events.
- */
-static struct visorchipset_busdev_notifiers chipset_notifiers = {
- .bus_create = chipset_bus_create,
- .bus_destroy = chipset_bus_destroy,
- .device_create = chipset_device_create,
- .device_destroy = chipset_device_destroy,
- .device_pause = chipset_device_pause,
- .device_resume = chipset_device_resume,
-};
-
-/** These functions are implemented in the chipset driver, and we call them
- * herein when we want to acknowledge a specific event.
- */
-static struct visorchipset_busdev_responders chipset_responders;
+static long long bus_count; /* number of bus instances */
+ /* ever-increasing */
/* filled in with info about parent chipset driver when we register with it */
static struct ultra_vbus_deviceinfo chipset_driverinfo;
/* filled in with info about this driver, wrt it servicing client busses */
static struct ultra_vbus_deviceinfo clientbus_driverinfo;
-/** list of visor_device structs, linked via .list_all */
+/* list of visor_device structs, linked via .list_all */
static LIST_HEAD(list_all_bus_instances);
-/** list of visor_device structs, linked via .list_all */
+/* list of visor_device structs, linked via .list_all */
static LIST_HEAD(list_all_device_instances);
static int
return 0;
}
-/* This is called automatically upon adding a visor_device (device_add), or
- * adding a visor_driver (visorbus_register_visor_driver), and returns 1 iff the
- * provided driver can control the specified device.
+/**
+ * visorbus_match() - called automatically upon adding a visor_device
+ * (device_add), or adding a visor_driver
+ * (visorbus_register_visor_driver)
+ * @xdev: struct device for the device being matched
+ * @xdrv: struct device_driver for driver to match device against
+ *
+ * Return: 1 iff the provided driver can control the specified device
*/
static int
visorbus_match(struct device *xdev, struct device_driver *xdrv)
return 0;
}
-/** This is called when device_unregister() is called for the bus device
- * instance, after all other tasks involved with destroying the device
- * are complete.
+/**
+ * visorbus_releae_busdevice() - called when device_unregister() is called for
+ * the bus device instance, after all other tasks
+ * involved with destroying the dev are complete
+ * @xdev: struct device for the bus being released
*/
static void
visorbus_release_busdevice(struct device *xdev)
kfree(dev);
}
-/** This is called when device_unregister() is called for each child
- * device instance.
+/**
+ * visorbus_release_device() - called when device_unregister() is called for
+ * each child device instance
+ * @xdev: struct device for the visor device being released
*/
static void
visorbus_release_device(struct device *xdev)
{
struct visor_device *dev = to_visor_device(xdev);
- if (dev->periodic_work) {
- visor_periodic_work_destroy(dev->periodic_work);
- dev->periodic_work = NULL;
- }
if (dev->visorchannel) {
visorchannel_destroy(dev->visorchannel);
dev->visorchannel = NULL;
kfree(dev);
}
-/* begin implementation of specific channel attributes to appear under
-* /sys/bus/visorbus<x>/dev<y>/channel
-*/
+/*
+ * begin implementation of specific channel attributes to appear under
+ * /sys/bus/visorbus<x>/dev<y>/channel
+ */
+
static ssize_t physaddr_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
/* end implementation of specific channel attributes */
-/* BUS instance attributes
+/*
+ * BUS instance attributes
*
* define & implement display of bus attributes under
- * /sys/bus/visorbus/busses/visorbus<n>.
- *
- * This is a bit hoaky because the kernel does not yet have the infrastructure
- * to separate bus INSTANCE attributes from bus TYPE attributes...
- * so we roll our own. See businst.c / businst.h.
- *
+ * /sys/bus/visorbus/devices/visorbus<n>.
*/
static ssize_t partition_handle_show(struct device *dev,
if (vdev->name)
partition_name = vdev->name;
shift = snprintf(pos, remain,
- "Client device / client driver info for %s eartition (vbus #%d):\n",
+ "Client device / client driver info for %s eartition (vbus #%u):\n",
partition_name, vdev->chipset_dev_no);
pos += shift;
remain -= shift;
NULL
};
-/* DRIVER attributes
+/*
+ * DRIVER attributes
*
* define & implement display of driver attributes under
* /sys/bus/visorbus/drivers/<drivername>.
- *
*/
static ssize_t
}
static void
-dev_periodic_work(void *xdev)
+dev_periodic_work(unsigned long __opaque)
{
- struct visor_device *dev = xdev;
+ struct visor_device *dev = (struct visor_device *)__opaque;
struct visor_driver *drv = to_visor_driver(dev->device.driver);
- down(&dev->visordriver_callback_lock);
if (drv->channel_interrupt)
drv->channel_interrupt(dev);
- up(&dev->visordriver_callback_lock);
- if (!visor_periodic_work_nextperiod(dev->periodic_work))
- put_device(&dev->device);
+ mod_timer(&dev->timer, jiffies + POLLJIFFIES_NORMALCHANNEL);
}
static void
dev_start_periodic_work(struct visor_device *dev)
{
- if (dev->being_removed)
+ if (dev->being_removed || dev->timer_active)
return;
/* now up by at least 2 */
get_device(&dev->device);
- if (!visor_periodic_work_start(dev->periodic_work))
- put_device(&dev->device);
+ dev->timer.expires = jiffies + POLLJIFFIES_NORMALCHANNEL;
+ add_timer(&dev->timer);
+ dev->timer_active = true;
}
static void
dev_stop_periodic_work(struct visor_device *dev)
{
- if (visor_periodic_work_stop(dev->periodic_work))
- put_device(&dev->device);
+ if (!dev->timer_active)
+ return;
+ del_timer_sync(&dev->timer);
+ dev->timer_active = false;
+ put_device(&dev->device);
}
-/** This is called automatically upon adding a visor_device (device_add), or
- * adding a visor_driver (visorbus_register_visor_driver), but only after
- * visorbus_match has returned 1 to indicate a successful match between
- * driver and device.
+/**
+ * visordriver_probe_device() - handle new visor device coming online
+ * @xdev: struct device for the visor device being probed
+ *
+ * This is called automatically upon adding a visor_device (device_add), or
+ * adding a visor_driver (visorbus_register_visor_driver), but only after
+ * visorbus_match() has returned 1 to indicate a successful match between
+ * driver and device.
+ *
+ * If successful, a reference to the device will be held onto via get_device().
+ *
+ * Return: 0 if successful, meaning the function driver's probe() function
+ * was successful with this device, otherwise a negative errno
+ * value indicating failure reason
*/
static int
visordriver_probe_device(struct device *xdev)
if (!drv->probe)
return -ENODEV;
- down(&dev->visordriver_callback_lock);
+ mutex_lock(&dev->visordriver_callback_lock);
dev->being_removed = false;
res = drv->probe(dev);
fix_vbus_dev_info(dev);
}
- up(&dev->visordriver_callback_lock);
+ mutex_unlock(&dev->visordriver_callback_lock);
return res;
}
-/** This is called when device_unregister() is called for each child device
- * instance, to notify the appropriate visorbus_driver that the device is
- * going away, and to decrease the reference count of the device.
+/**
+ * visordriver_remove_device() - handle visor device going away
+ * @xdev: struct device for the visor device being removed
+ *
+ * This is called when device_unregister() is called for each child device
+ * instance, to notify the appropriate visorbus function driver that the device
+ * is going away, and to decrease the reference count of the device.
+ *
+ * Return: 0 iff successful
*/
static int
visordriver_remove_device(struct device *xdev)
dev = to_visor_device(xdev);
drv = to_visor_driver(xdev->driver);
- down(&dev->visordriver_callback_lock);
+ mutex_lock(&dev->visordriver_callback_lock);
dev->being_removed = true;
if (drv->remove)
drv->remove(dev);
- up(&dev->visordriver_callback_lock);
+ mutex_unlock(&dev->visordriver_callback_lock);
dev_stop_periodic_work(dev);
put_device(&dev->device);
return 0;
}
-/** A particular type of visor driver calls this function to register
- * the driver. The caller MUST fill in the following fields within the
- * #drv structure:
- * name, version, owner, channel_types, probe, remove
+/**
+ * visorbus_register_visor_driver() - registers the provided visor driver
+ * for handling one or more visor device
+ * types (channel_types)
+ * @drv: the driver to register
+ *
+ * A visor function driver calls this function to register
+ * the driver. The caller MUST fill in the following fields within the
+ * #drv structure:
+ * name, version, owner, channel_types, probe, remove
*
- * Here's how the whole Linux bus / driver / device model works.
+ * Here's how the whole Linux bus / driver / device model works.
*
- * At system start-up, the visorbus kernel module is loaded, which registers
- * visorbus_type as a bus type, using bus_register().
+ * At system start-up, the visorbus kernel module is loaded, which registers
+ * visorbus_type as a bus type, using bus_register().
*
- * All kernel modules that support particular device types on a
- * visorbus bus are loaded. Each of these kernel modules calls
- * visorbus_register_visor_driver() in their init functions, passing a
- * visor_driver struct. visorbus_register_visor_driver() in turn calls
- * register_driver(&visor_driver.driver). This .driver member is
- * initialized with generic methods (like probe), whose sole responsibility
- * is to act as a broker for the real methods, which are within the
- * visor_driver struct. (This is the way the subclass behavior is
- * implemented, since visor_driver is essentially a subclass of the
- * generic driver.) Whenever a driver_register() happens, core bus code in
- * the kernel does (see device_attach() in drivers/base/dd.c):
+ * All kernel modules that support particular device types on a
+ * visorbus bus are loaded. Each of these kernel modules calls
+ * visorbus_register_visor_driver() in their init functions, passing a
+ * visor_driver struct. visorbus_register_visor_driver() in turn calls
+ * register_driver(&visor_driver.driver). This .driver member is
+ * initialized with generic methods (like probe), whose sole responsibility
+ * is to act as a broker for the real methods, which are within the
+ * visor_driver struct. (This is the way the subclass behavior is
+ * implemented, since visor_driver is essentially a subclass of the
+ * generic driver.) Whenever a driver_register() happens, core bus code in
+ * the kernel does (see device_attach() in drivers/base/dd.c):
*
- * for each dev associated with the bus (the bus that driver is on) that
- * does not yet have a driver
- * if bus.match(dev,newdriver) == yes_matched ** .match specified
- * ** during bus_register().
- * newdriver.probe(dev) ** for visor drivers, this will call
- * ** the generic driver.probe implemented in visorbus.c,
- * ** which in turn calls the probe specified within the
- * ** struct visor_driver (which was specified by the
- * ** actual device driver as part of
- * ** visorbus_register_visor_driver()).
+ * for each dev associated with the bus (the bus that driver is on) that
+ * does not yet have a driver
+ * if bus.match(dev,newdriver) == yes_matched ** .match specified
+ * ** during bus_register().
+ * newdriver.probe(dev) ** for visor drivers, this will call
+ * ** the generic driver.probe implemented in visorbus.c,
+ * ** which in turn calls the probe specified within the
+ * ** struct visor_driver (which was specified by the
+ * ** actual device driver as part of
+ * ** visorbus_register_visor_driver()).
*
- * The above dance also happens when a new device appears.
- * So the question is, how are devices created within the system?
- * Basically, just call device_add(dev). See pci_bus_add_devices().
- * pci_scan_device() shows an example of how to build a device struct. It
- * returns the newly-created struct to pci_scan_single_device(), who adds it
- * to the list of devices at PCIBUS.devices. That list of devices is what
- * is traversed by pci_bus_add_devices().
+ * The above dance also happens when a new device appears.
+ * So the question is, how are devices created within the system?
+ * Basically, just call device_add(dev). See pci_bus_add_devices().
+ * pci_scan_device() shows an example of how to build a device struct. It
+ * returns the newly-created struct to pci_scan_single_device(), who adds it
+ * to the list of devices at PCIBUS.devices. That list of devices is what
+ * is traversed by pci_bus_add_devices().
*
+ * Return: integer indicating success (zero) or failure (non-zero)
*/
int visorbus_register_visor_driver(struct visor_driver *drv)
{
drv->driver.remove = visordriver_remove_device;
drv->driver.owner = drv->owner;
- /* driver_register does this:
+ /*
+ * driver_register does this:
* bus_add_driver(drv)
* ->if (drv.bus) ** (bus_type) **
* driver_attach(drv)
}
EXPORT_SYMBOL_GPL(visorbus_register_visor_driver);
-/** A particular type of visor driver calls this function to unregister
- * the driver, i.e., within its module_exit function.
+/**
+ * visorbus_unregister_visor_driver() - unregisters the provided driver
+ * @drv: the driver to unregister
+ *
+ * A visor function driver calls this function to unregister the driver,
+ * i.e., within its module_exit function.
*/
void
visorbus_unregister_visor_driver(struct visor_driver *drv)
}
EXPORT_SYMBOL_GPL(visorbus_unregister_visor_driver);
+/**
+ * visorbus_read_channel() - reads from the designated channel into
+ * the provided buffer
+ * @dev: the device whose channel is read from
+ * @offset: the offset into the channel at which reading starts
+ * @dest: the destination buffer that is written into from the channel
+ * @nbytes: the number of bytes to read from the channel
+ *
+ * If receiving a message, use the visorchannel_signalremove()
+ * function instead.
+ *
+ * Return: integer indicating success (zero) or failure (non-zero)
+ */
int
visorbus_read_channel(struct visor_device *dev, unsigned long offset,
void *dest, unsigned long nbytes)
}
EXPORT_SYMBOL_GPL(visorbus_read_channel);
+/**
+ * visorbus_write_channel() - writes the provided buffer into the designated
+ * channel
+ * @dev: the device whose channel is written to
+ * @offset: the offset into the channel at which writing starts
+ * @src: the source buffer that is written into the channel
+ * @nbytes: the number of bytes to write into the channel
+ *
+ * If sending a message, use the visorchannel_signalinsert()
+ * function instead.
+ *
+ * Return: integer indicating success (zero) or failure (non-zero)
+ */
int
visorbus_write_channel(struct visor_device *dev, unsigned long offset,
void *src, unsigned long nbytes)
}
EXPORT_SYMBOL_GPL(visorbus_write_channel);
-int
-visorbus_clear_channel(struct visor_device *dev, unsigned long offset, u8 ch,
- unsigned long nbytes)
-{
- return visorchannel_clear(dev->visorchannel, offset, ch, nbytes);
-}
-EXPORT_SYMBOL_GPL(visorbus_clear_channel);
-
-/** We don't really have a real interrupt, so for now we just call the
- * interrupt function periodically...
+/**
+ * visorbus_enable_channel_interrupts() - enables interrupts on the
+ * designated device
+ * @dev: the device on which to enable interrupts
+ *
+ * Currently we don't yet have a real interrupt, so for now we just call the
+ * interrupt function periodically via a timer.
*/
void
visorbus_enable_channel_interrupts(struct visor_device *dev)
}
EXPORT_SYMBOL_GPL(visorbus_enable_channel_interrupts);
+/**
+ * visorbus_disable_channel_interrupts() - disables interrupts on the
+ * designated device
+ * @dev: the device on which to disable interrupts
+ */
void
visorbus_disable_channel_interrupts(struct visor_device *dev)
{
}
EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts);
-/** This is how everything starts from the device end.
- * This function is called when a channel first appears via a ControlVM
- * message. In response, this function allocates a visor_device to
- * correspond to the new channel, and attempts to connect it the appropriate
- * driver. If the appropriate driver is found, the visor_driver.probe()
- * function for that driver will be called, and will be passed the new
- * visor_device that we just created.
+/**
+ * create_visor_device() - create visor device as a result of receiving the
+ * controlvm device_create message for a new device
+ * @dev: a freshly-zeroed struct visor_device, containing only filled-in values
+ * for chipset_bus_no and chipset_dev_no, that will be initialized
+ *
+ * This is how everything starts from the device end.
+ * This function is called when a channel first appears via a ControlVM
+ * message. In response, this function allocates a visor_device to
+ * correspond to the new channel, and attempts to connect it the appropriate
+ * driver. If the appropriate driver is found, the visor_driver.probe()
+ * function for that driver will be called, and will be passed the new
+ * visor_device that we just created.
*
- * It's ok if the appropriate driver is not yet loaded, because in that case
- * the new device struct will just stick around in the bus' list of devices.
- * When the appropriate driver calls visorbus_register_visor_driver(), the
- * visor_driver.probe() for the new driver will be called with the new
- * device.
+ * It's ok if the appropriate driver is not yet loaded, because in that case
+ * the new device struct will just stick around in the bus' list of devices.
+ * When the appropriate driver calls visorbus_register_visor_driver(), the
+ * visor_driver.probe() for the new driver will be called with the new
+ * device.
+ *
+ * Return: 0 if successful, otherwise the negative value returned by
+ * device_add() indicating the reason for failure
*/
static int
create_visor_device(struct visor_device *dev)
POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, chipset_dev_no, chipset_bus_no,
POSTCODE_SEVERITY_INFO);
- sema_init(&dev->visordriver_callback_lock, 1); /* unlocked */
+ mutex_init(&dev->visordriver_callback_lock);
dev->device.bus = &visorbus_type;
dev->device.groups = visorbus_channel_groups;
device_initialize(&dev->device);
dev->device.release = visorbus_release_device;
/* keep a reference just for us (now 2) */
get_device(&dev->device);
- dev->periodic_work =
- visor_periodic_work_create(POLLJIFFIES_NORMALCHANNEL,
- periodic_dev_workqueue,
- dev_periodic_work,
- dev, dev_name(&dev->device));
- if (!dev->periodic_work) {
- POSTCODE_LINUX_3(DEVICE_CREATE_FAILURE_PC, chipset_dev_no,
- DIAG_SEVERITY_ERR);
- err = -EINVAL;
- goto err_put;
- }
+ init_timer(&dev->timer);
+ dev->timer.data = (unsigned long)(dev);
+ dev->timer.function = dev_periodic_work;
- /* bus_id must be a unique name with respect to this bus TYPE
+ /*
+ * bus_id must be a unique name with respect to this bus TYPE
* (NOT bus instance). That's why we need to include the bus
* number within the name.
*/
dev_set_name(&dev->device, "vbus%u:dev%u",
chipset_bus_no, chipset_dev_no);
- /* device_add does this:
+ /*
+ * device_add does this:
* bus_add_device(dev)
* ->device_attach(dev)
* ->for each driver drv registered on the bus that dev is on
return 0;
}
-/* Write the contents of <info> to the struct
- * spar_vbus_channel_protocol.chp_info.
+/**
+ * write_vbus_chp_info() - write the contents of <info> to the struct
+ * spar_vbus_channel_protocol.chp_info
+ * @chan: indentifies the s-Par channel that will be updated
+ * @hdr_info: used to find appropriate channel offset to write data
+ * @info: contains the information to write
+ *
+ * Writes chipset info into the channel memory to be used for diagnostic
+ * purposes.
+ *
+ * Returns no value since this is debug information and not needed for
+ * device functionality.
*/
-
-static int
+static void
write_vbus_chp_info(struct visorchannel *chan,
struct spar_vbus_headerinfo *hdr_info,
struct ultra_vbus_deviceinfo *info)
int off = sizeof(struct channel_header) + hdr_info->chp_info_offset;
if (hdr_info->chp_info_offset == 0)
- return -EFAULT;
+ return;
- if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
- return -EFAULT;
- return 0;
+ visorchannel_write(chan, off, info, sizeof(*info));
}
-/* Write the contents of <info> to the struct
- * spar_vbus_channel_protocol.bus_info.
+/**
+ * write_vbus_bus_info() - write the contents of <info> to the struct
+ * spar_vbus_channel_protocol.bus_info
+ * @chan: indentifies the s-Par channel that will be updated
+ * @hdr_info: used to find appropriate channel offset to write data
+ * @info: contains the information to write
+ *
+ * Writes bus info into the channel memory to be used for diagnostic
+ * purposes.
+ *
+ * Returns no value since this is debug information and not needed for
+ * device functionality.
*/
-
-static int
+static void
write_vbus_bus_info(struct visorchannel *chan,
struct spar_vbus_headerinfo *hdr_info,
struct ultra_vbus_deviceinfo *info)
int off = sizeof(struct channel_header) + hdr_info->bus_info_offset;
if (hdr_info->bus_info_offset == 0)
- return -EFAULT;
+ return;
- if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
- return -EFAULT;
- return 0;
+ visorchannel_write(chan, off, info, sizeof(*info));
}
-/* Write the contents of <info> to the
- * struct spar_vbus_channel_protocol.dev_info[<devix>].
+/**
+ * write_vbus_dev_info() - write the contents of <info> to the struct
+ * spar_vbus_channel_protocol.dev_info[<devix>]
+ * @chan: indentifies the s-Par channel that will be updated
+ * @hdr_info: used to find appropriate channel offset to write data
+ * @info: contains the information to write
+ * @devix: the relative device number (0..n-1) of the device on the bus
+ *
+ * Writes device info into the channel memory to be used for diagnostic
+ * purposes.
+ *
+ * Returns no value since this is debug information and not needed for
+ * device functionality.
*/
-static int
+static void
write_vbus_dev_info(struct visorchannel *chan,
struct spar_vbus_headerinfo *hdr_info,
struct ultra_vbus_deviceinfo *info, int devix)
(hdr_info->device_info_struct_bytes * devix);
if (hdr_info->dev_info_offset == 0)
- return -EFAULT;
+ return;
- if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
- return -EFAULT;
- return 0;
+ visorchannel_write(chan, off, info, sizeof(*info));
}
-/* For a child device just created on a client bus, fill in
- * information about the driver that is controlling this device into
- * the the appropriate slot within the vbus channel of the bus
- * instance.
+/**
+ * fix_vbus_dev_info() - for a child device just created on a client bus, fill
+ * in information about the driver that is controlling
+ * this device into the the appropriate slot within the
+ * vbus channel of the bus instance
+ * @visordev: struct visor_device for the desired device
*/
static void
fix_vbus_dev_info(struct visor_device *visordev)
visordrv = to_visor_driver(visordev->device.driver);
- /* Within the list of device types (by GUID) that the driver
+ /*
+ * Within the list of device types (by GUID) that the driver
* says it supports, find out which one of those types matches
* the type of this device, so that we can include the device
* type name
visordrv->vertag);
write_vbus_dev_info(bdev->visorchannel, hdr_info, &dev_info, dev_no);
- /* Re-write bus+chipset info, because it is possible that this
- * was previously written by our evil counterpart, virtpci.
- */
+ /*
+ * Re-write bus+chipset info, because it is possible that this
+ * was previously written by our evil counterpart, virtpci.
+ */
write_vbus_chp_info(bdev->visorchannel, hdr_info, &chipset_driverinfo);
write_vbus_bus_info(bdev->visorchannel, hdr_info,
&clientbus_driverinfo);
}
-/** Create a device instance for the visor bus itself.
+/**
+ * create_bus_instance() - create a device instance for the visor bus itself
+ * @dev: struct visor_device indicating the bus instance
+ *
+ * Return: 0 for success, otherwise negative errno value indicating reason for
+ * failure
*/
static int
create_bus_instance(struct visor_device *dev)
return 0;
}
-/** Remove a device instance for the visor bus itself.
+/**
+ * remove_bus_instance() - remove a device instance for the visor bus itself
+ * @dev: struct visor_device indentifying the bus to remove
*/
static void
remove_bus_instance(struct visor_device *dev)
{
- /* Note that this will result in the release method for
+ /*
+ * Note that this will result in the release method for
* dev->dev being called, which will call
* visorbus_release_busdevice(). This has something to do with
* the put_device() done in device_unregister(), but I have never
device_unregister(&dev->device);
}
-/** Create and register the one-and-only one instance of
- * the visor bus type (visorbus_type).
+/**
+ * create_bus_type() - create and register the one-and-only one instance of
+ * the visor bus type (visorbus_type)
+ * Return: 0 for success, otherwise negative errno value returned by
+ * bus_register() indicating the reason for failure
*/
static int
create_bus_type(void)
return busreg_rc;
}
-/** Remove the one-and-only one instance of the visor bus type (visorbus_type).
+/**
+ * remove_bus_type() - remove the one-and-only one instance of the visor bus
+ * type (visorbus_type)
*/
static void
remove_bus_type(void)
bus_unregister(&visorbus_type);
}
-/** Remove all child visor bus device instances.
+/**
+ * remove_all_visor_devices() - remove all child visor bus device instances
*/
static void
remove_all_visor_devices(void)
}
}
-static void
+void
chipset_bus_create(struct visor_device *dev)
{
int rc;
POSTCODE_LINUX_3(CHIPSET_INIT_SUCCESS_PC, bus_no,
POSTCODE_SEVERITY_INFO);
- if (chipset_responders.bus_create)
- (*chipset_responders.bus_create) (dev, rc);
+ bus_create_response(dev, rc);
}
-static void
+void
chipset_bus_destroy(struct visor_device *dev)
{
remove_bus_instance(dev);
- if (chipset_responders.bus_destroy)
- (*chipset_responders.bus_destroy)(dev, 0);
+ bus_destroy_response(dev, 0);
}
-static void
+void
chipset_device_create(struct visor_device *dev_info)
{
int rc;
POSTCODE_SEVERITY_INFO);
rc = create_visor_device(dev_info);
- if (chipset_responders.device_create)
- chipset_responders.device_create(dev_info, rc);
+ device_create_response(dev_info, rc);
if (rc < 0)
POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
POSTCODE_SEVERITY_INFO);
}
-static void
+void
chipset_device_destroy(struct visor_device *dev_info)
{
remove_visor_device(dev_info);
- if (chipset_responders.device_destroy)
- (*chipset_responders.device_destroy) (dev_info, 0);
+ device_destroy_response(dev_info, 0);
}
-/* This is the callback function specified for a function driver, to
- * be called when a pending "pause device" operation has been
- * completed.
+/**
+ * pause_state_change_complete() - the callback function to be called by a
+ * visorbus function driver when a
+ * pending "pause device" operation has
+ * completed
+ * @dev: struct visor_device identifying the paused device
+ * @status: 0 iff the pause state change completed successfully, otherwise
+ * a negative errno value indicating the reason for failure
*/
static void
pause_state_change_complete(struct visor_device *dev, int status)
return;
dev->pausing = false;
- if (!chipset_responders.device_pause) /* this can never happen! */
- return;
- /* Notify the chipset driver that the pause is complete, which
- * will presumably want to send some sort of response to the
- * initiator.
- */
- (*chipset_responders.device_pause) (dev, status);
+ device_pause_response(dev, status);
}
-/* This is the callback function specified for a function driver, to
- * be called when a pending "resume device" operation has been
- * completed.
+/**
+ * resume_state_change_complete() - the callback function to be called by a
+ * visorbus function driver when a
+ * pending "resume device" operation has
+ * completed
+ * @dev: struct visor_device identifying the resumed device
+ * @status: 0 iff the resume state change completed successfully, otherwise
+ * a negative errno value indicating the reason for failure
*/
static void
resume_state_change_complete(struct visor_device *dev, int status)
return;
dev->resuming = false;
- if (!chipset_responders.device_resume) /* this can never happen! */
- return;
- /* Notify the chipset driver that the resume is complete,
+ /*
+ * Notify the chipset driver that the resume is complete,
* which will presumably want to send some sort of response to
* the initiator.
*/
- (*chipset_responders.device_resume) (dev, status);
+ device_resume_response(dev, status);
}
-/* Tell the subordinate function driver for a specific device to pause
- * or resume that device. Result is returned asynchronously via a
- * callback function.
+/**
+ * initiate_chipset_device_pause_resume() - start a pause or resume operation
+ * for a visor device
+ * @dev: struct visor_device identifying the device being paused or resumed
+ * @is_pause: true to indicate pause operation, false to indicate resume
+ *
+ * Tell the subordinate function driver for a specific device to pause
+ * or resume that device. Success/failure result is returned asynchronously
+ * via a callback function; see pause_state_change_complete() and
+ * resume_state_change_complete().
*/
static void
initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
void (*notify_func)(struct visor_device *dev, int response) = NULL;
if (is_pause)
- notify_func = chipset_responders.device_pause;
+ notify_func = device_pause_response;
else
- notify_func = chipset_responders.device_resume;
+ notify_func = device_resume_response;
if (!notify_func)
return;
return;
}
- /* Note that even though both drv->pause() and drv->resume
+ /*
+ * Note that even though both drv->pause() and drv->resume
* specify a callback function, it is NOT necessary for us to
* increment our local module usage count. Reason is, there
* is already a linkage dependency between child function
}
}
-static void
+/**
+ * chipset_device_pause() - start a pause operation for a visor device
+ * @dev_info: struct visor_device identifying the device being paused
+ *
+ * Tell the subordinate function driver for a specific device to pause
+ * that device. Success/failure result is returned asynchronously
+ * via a callback function; see pause_state_change_complete().
+ */
+void
chipset_device_pause(struct visor_device *dev_info)
{
initiate_chipset_device_pause_resume(dev_info, true);
}
-static void
+/**
+ * chipset_device_resume() - start a resume operation for a visor device
+ * @dev_info: struct visor_device identifying the device being resumed
+ *
+ * Tell the subordinate function driver for a specific device to resume
+ * that device. Success/failure result is returned asynchronously
+ * via a callback function; see resume_state_change_complete().
+ */
+void
chipset_device_resume(struct visor_device *dev_info)
{
initiate_chipset_device_pause_resume(dev_info, false);
}
-struct channel_size_info {
- uuid_le guid;
- unsigned long min_size;
- unsigned long max_size;
-};
-
int
visorbus_init(void)
{
goto error;
}
- periodic_dev_workqueue = create_singlethread_workqueue("visorbus_dev");
- if (!periodic_dev_workqueue) {
- POSTCODE_LINUX_2(CREATE_WORKQUEUE_PC, DIAG_SEVERITY_ERR);
- err = -ENOMEM;
- goto error;
- }
-
- /* This enables us to receive notifications when devices appear for
- * which this service partition is to be a server for.
- */
- visorchipset_register_busdev(&chipset_notifiers,
- &chipset_responders,
- &chipset_driverinfo);
+ bus_device_info_init(&chipset_driverinfo,
+ "chipset", "visorchipset",
+ VERSION, NULL);
return 0;
{
struct list_head *listentry, *listtmp;
- visorchipset_register_busdev(NULL, NULL, NULL);
remove_all_visor_devices();
- flush_workqueue(periodic_dev_workqueue); /* better not be any work! */
- destroy_workqueue(periodic_dev_workqueue);
- periodic_dev_workqueue = NULL;
-
- if (periodic_test_workqueue) {
- cancel_delayed_work(&periodic_work);
- flush_workqueue(periodic_test_workqueue);
- destroy_workqueue(periodic_test_workqueue);
- periodic_test_workqueue = NULL;
- }
-
list_for_each_safe(listentry, listtmp, &list_all_bus_instances) {
struct visor_device *dev = list_entry(listentry,
struct visor_device,
remove_bus_type();
}
-module_param_named(debug, visorbus_debug, int, S_IRUGO);
-MODULE_PARM_DESC(visorbus_debug, "1 to debug");
-
module_param_named(forcematch, visorbus_forcematch, int, S_IRUGO);
MODULE_PARM_DESC(visorbus_forcematch,
"1 to force a successful dev <--> drv match");
module_param_named(forcenomatch, visorbus_forcenomatch, int, S_IRUGO);
MODULE_PARM_DESC(visorbus_forcenomatch,
"1 to force an UNsuccessful dev <--> drv match");
-
-module_param_named(debugref, visorbus_debugref, int, S_IRUGO);
-MODULE_PARM_DESC(visorbus_debugref, "1 to debug reference counting");