cregit-Linux how code gets into the kernel

Release 4.7 drivers/s390/cio/ccwgroup.c

Directory: drivers/s390/cio
/*
 *  bus driver for ccwgroup
 *
 *  Copyright IBM Corp. 2002, 2012
 *
 *  Author(s): Arnd Bergmann (arndb@de.ibm.com)
 *             Cornelia Huck (cornelia.huck@de.ibm.com)
 */
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/dcache.h>

#include <asm/cio.h>
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>

#include "device.h"


#define CCW_BUS_ID_SIZE		10

/* In Linux 2.4, we had a channel device layer called "chandev"
 * that did all sorts of obscure stuff for networking devices.
 * This is another driver that serves as a replacement for just
 * one of its functions, namely the translation of single subchannels
 * to devices that use multiple subchannels.
 */


static struct bus_type ccwgroup_bus_type;


static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) { int i; char str[8]; for (i = 0; i < gdev->count; i++) { sprintf(str, "cdev%d", i); sysfs_remove_link(&gdev->dev.kobj, str); sysfs_remove_link(&gdev->cdev[i]->dev.kobj, "group_device"); } }

Contributors

PersonTokensPropCommitsCommitProp
martin schwidefskymartin schwidefsky75100.00%2100.00%
Total75100.00%2100.00%

/* * Remove references from ccw devices to ccw group device and from * ccw group device to ccw devices. */
static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev) { struct ccw_device *cdev; int i; for (i = 0; i < gdev->count; i++) { cdev = gdev->cdev[i]; if (!cdev) continue; spin_lock_irq(cdev->ccwlock); dev_set_drvdata(&cdev->dev, NULL); spin_unlock_irq(cdev->ccwlock); gdev->cdev[i] = NULL; put_device(&cdev->dev); } }

Contributors

PersonTokensPropCommitsCommitProp
peter oberparleiterpeter oberparleiter92100.00%1100.00%
Total92100.00%1100.00%

/** * ccwgroup_set_online() - enable a ccwgroup device * @gdev: target ccwgroup device * * This function attempts to put the ccwgroup device into the online state. * Returns: * %0 on success and a negative error value on failure. */
int ccwgroup_set_online(struct ccwgroup_device *gdev) { struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); int ret = -EINVAL; if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) return -EAGAIN; if (gdev->state == CCWGROUP_ONLINE) goto out; if (gdrv->set_online) ret = gdrv->set_online(gdev); if (ret) goto out; gdev->state = CCWGROUP_ONLINE; out: atomic_set(&gdev->onoff, 0); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott6966.35%233.33%
alan sternalan stern1716.35%116.67%
cornelia huckcornelia huck1615.38%233.33%
peter oberparleiterpeter oberparleiter21.92%116.67%
Total104100.00%6100.00%

EXPORT_SYMBOL(ccwgroup_set_online); /** * ccwgroup_set_offline() - disable a ccwgroup device * @gdev: target ccwgroup device * * This function attempts to put the ccwgroup device into the offline state. * Returns: * %0 on success and a negative error value on failure. */
int ccwgroup_set_offline(struct ccwgroup_device *gdev) { struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); int ret = -EINVAL; if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) return -EAGAIN; if (gdev->state == CCWGROUP_OFFLINE) goto out; if (gdrv->set_offline) ret = gdrv->set_offline(gdev); if (ret) goto out; gdev->state = CCWGROUP_OFFLINE; out: atomic_set(&gdev->onoff, 0); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott5754.81%240.00%
peter oberparleiterpeter oberparleiter2322.12%120.00%
martin schwidefskymartin schwidefsky1918.27%120.00%
alan sternalan stern54.81%120.00%
Total104100.00%5100.00%

EXPORT_SYMBOL(ccwgroup_set_offline);
static ssize_t ccwgroup_online_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); unsigned long value; int ret; device_lock(dev); if (!dev->driver) { ret = -EINVAL; goto out; } ret = kstrtoul(buf, 0, &value); if (ret) goto out; if (value == 1) ret = ccwgroup_set_online(gdev); else if (value == 0) ret = ccwgroup_set_offline(gdev); else ret = -EINVAL; out: device_unlock(dev); return (ret == 0) ? count : ret; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott13299.25%266.67%
jingoo hanjingoo han10.75%133.33%
Total133100.00%3100.00%


static ssize_t ccwgroup_online_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); int online; online = (gdev->state == CCWGROUP_ONLINE) ? 1 : 0; return scnprintf(buf, PAGE_SIZE, "%d\n", online); }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott59100.00%1100.00%
Total59100.00%1100.00%

/* * Provide an 'ungroup' attribute so the user can remove group devices no * longer needed or accidentially created. Saves memory :) */
static void ccwgroup_ungroup(struct ccwgroup_device *gdev) { mutex_lock(&gdev->reg_mutex); if (device_is_registered(&gdev->dev)) { __ccwgroup_remove_symlinks(gdev); device_unregister(&gdev->dev); __ccwgroup_remove_cdev_refs(gdev); } mutex_unlock(&gdev->reg_mutex); }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott5189.47%150.00%
tejun heotejun heo610.53%150.00%
Total57100.00%2100.00%


static ssize_t ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); int rc = 0; /* Prevent concurrent online/offline processing and ungrouping. */ if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) return -EAGAIN; if (gdev->state != CCWGROUP_OFFLINE) { rc = -EINVAL; goto out; } if (device_remove_file_self(dev, attr)) ccwgroup_ungroup(gdev); else rc = -ENODEV; out: if (rc) { /* Release onoff "lock" when ungrouping failed. */ atomic_set(&gdev->onoff, 0); return rc; } return count; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott9375.61%233.33%
peter oberparleiterpeter oberparleiter1512.20%116.67%
tejun heotejun heo97.32%116.67%
martin schwidefskymartin schwidefsky43.25%116.67%
alan sternalan stern21.63%116.67%
Total123100.00%6100.00%

static DEVICE_ATTR(ungroup, 0200, NULL, ccwgroup_ungroup_store); static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store); static struct attribute *ccwgroup_attrs[] = { &dev_attr_online.attr, &dev_attr_ungroup.attr, NULL, }; static struct attribute_group ccwgroup_attr_group = { .attrs = ccwgroup_attrs, }; static const struct attribute_group *ccwgroup_attr_groups[] = { &ccwgroup_attr_group, NULL, };
static void ccwgroup_ungroup_workfn(struct work_struct *work) { struct ccwgroup_device *gdev = container_of(work, struct ccwgroup_device, ungroup_work); ccwgroup_ungroup(gdev); put_device(&gdev->dev); }

Contributors

PersonTokensPropCommitsCommitProp
tejun heotejun heo3179.49%150.00%
sebastian ottsebastian ott820.51%150.00%
Total39100.00%2100.00%


static void ccwgroup_release(struct device *dev) { kfree(to_ccwgroupdev(dev)); }

Contributors

PersonTokensPropCommitsCommitProp
martin schwidefskymartin schwidefsky1684.21%250.00%
peter oberparleiterpeter oberparleiter210.53%125.00%
sebastian ottsebastian ott15.26%125.00%
Total19100.00%4100.00%


static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) { char str[8]; int i, rc; for (i = 0; i < gdev->count; i++) { rc = sysfs_create_link(&gdev->cdev[i]->dev.kobj, &gdev->dev.kobj, "group_device"); if (rc) { for (--i; i >= 0; i--) sysfs_remove_link(&gdev->cdev[i]->dev.kobj, "group_device"); return rc; } } for (i = 0; i < gdev->count; i++) { sprintf(str, "cdev%d", i); rc = sysfs_create_link(&gdev->dev.kobj, &gdev->cdev[i]->dev.kobj, str); if (rc) { for (--i; i >= 0; i--) { sprintf(str, "cdev%d", i); sysfs_remove_link(&gdev->dev.kobj, str); } for (i = 0; i < gdev->count; i++) sysfs_remove_link(&gdev->cdev[i]->dev.kobj, "group_device"); return rc; } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
martin schwidefskymartin schwidefsky234100.00%1100.00%
Total234100.00%1100.00%


static int __get_next_id(const char **buf, struct ccw_dev_id *id) { unsigned int cssid, ssid, devno; int ret = 0, len; char *start, *end; start = (char *)*buf; end = strchr(start, ','); if (!end) { /* Last entry. Strip trailing newline, if applicable. */ end = strchr(start, '\n'); if (end) *end = '\0'; len = strlen(start) + 1; } else { len = end - start + 1; end++; } if (len <= CCW_BUS_ID_SIZE) { if (sscanf(start, "%2x.%1x.%04x", &cssid, &ssid, &devno) != 3) ret = -EINVAL; } else ret = -EINVAL; if (!ret) { id->ssid = ssid; id->devno = devno; } *buf = end; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
ursula braun-krahlursula braun-krahl11667.44%133.33%
sebastian ottsebastian ott5531.98%133.33%
kay sieverskay sievers10.58%133.33%
Total172100.00%3100.00%

/** * ccwgroup_create_dev() - create and register a ccw group device * @parent: parent device for the new device * @gdrv: driver for the new group device * @num_devices: number of slave devices * @buf: buffer containing comma separated bus ids of slave devices * * Create and register a new ccw group device as a child of @parent. Slave * devices are obtained from the list of bus ids given in @buf. * Returns: * %0 on success and an error code on failure. * Context: * non-atomic */
int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, int num_devices, const char *buf) { struct ccwgroup_device *gdev; struct ccw_dev_id dev_id; int rc, i; gdev = kzalloc(sizeof(*gdev) + num_devices * sizeof(gdev->cdev[0]), GFP_KERNEL); if (!gdev) return -ENOMEM; atomic_set(&gdev->onoff, 0); mutex_init(&gdev->reg_mutex); mutex_lock(&gdev->reg_mutex); INIT_WORK(&gdev->ungroup_work, ccwgroup_ungroup_workfn); gdev->count = num_devices; gdev->dev.bus = &ccwgroup_bus_type; gdev->dev.parent = parent; gdev->dev.release = ccwgroup_release; device_initialize(&gdev->dev); for (i = 0; i < num_devices && buf; i++) { rc = __get_next_id(&buf, &dev_id); if (rc != 0) goto error; gdev->cdev[i] = get_ccwdev_by_dev_id(&dev_id); /* * All devices have to be of the same type in * order to be grouped. */ if (!gdev->cdev[i] || !gdev->cdev[i]->drv || gdev->cdev[i]->drv != gdev->cdev[0]->drv || gdev->cdev[i]->id.driver_info != gdev->cdev[0]->id.driver_info) { rc = -EINVAL; goto error; } /* Don't allow a device to belong to more than one group. */ spin_lock_irq(gdev->cdev[i]->ccwlock); if (dev_get_drvdata(&gdev->cdev[i]->dev)) { spin_unlock_irq(gdev->cdev[i]->ccwlock); rc = -EINVAL; goto error; } dev_set_drvdata(&gdev->cdev[i]->dev, gdev); spin_unlock_irq(gdev->cdev[i]->ccwlock); } /* Check for sufficient number of bus ids. */ if (i < num_devices) { rc = -EINVAL; goto error; } /* Check for trailing stuff. */ if (i == num_devices && strlen(buf) > 0) { rc = -EINVAL; goto error; } dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev)); gdev->dev.groups = ccwgroup_attr_groups; if (gdrv) { gdev->dev.driver = &gdrv->driver; rc = gdrv->setup ? gdrv->setup(gdev) : 0; if (rc) goto error; } rc = device_add(&gdev->dev); if (rc) goto error; rc = __ccwgroup_create_symlinks(gdev); if (rc) { device_del(&gdev->dev); goto error; } mutex_unlock(&gdev->reg_mutex); return 0; error: for (i = 0; i < num_devices; i++) if (gdev->cdev[i]) { spin_lock_irq(gdev->cdev[i]->ccwlock); if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) dev_set_drvdata(&gdev->cdev[i]->dev, NULL); spin_unlock_irq(gdev->cdev[i]->ccwlock); put_device(&gdev->cdev[i]->dev); gdev->cdev[i] = NULL; } mutex_unlock(&gdev->reg_mutex); put_device(&gdev->dev); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott29947.46%422.22%
martin schwidefskymartin schwidefsky15324.29%15.56%
andrew mortonandrew morton609.52%316.67%
cornelia huckcornelia huck446.98%633.33%
peter oberparleiterpeter oberparleiter386.03%15.56%
ursula braun-krahlursula braun-krahl253.97%15.56%
tejun heotejun heo101.59%15.56%
eric sesterhenneric sesterhenn10.16%15.56%
Total630100.00%18100.00%

EXPORT_SYMBOL(ccwgroup_create_dev);
static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, void *data) { struct ccwgroup_device *gdev = to_ccwgroupdev(data); if (action == BUS_NOTIFY_UNBIND_DRIVER) { get_device(&gdev->dev); schedule_work(&gdev->ungroup_work); } return NOTIFY_OK; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott2646.43%233.33%
martin schwidefskymartin schwidefsky1221.43%116.67%
tejun heotejun heo1017.86%116.67%
andrew mortonandrew morton712.50%116.67%
yani ioannouyani ioannou11.79%116.67%
Total56100.00%6100.00%

static struct notifier_block ccwgroup_nb = { .notifier_call = ccwgroup_notifier };
static int __init init_ccwgroup(void) { int ret; ret = bus_register(&ccwgroup_bus_type); if (ret) return ret; ret = bus_register_notifier(&ccwgroup_bus_type, &ccwgroup_nb); if (ret) bus_unregister(&ccwgroup_bus_type); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott3568.63%233.33%
martin schwidefskymartin schwidefsky1019.61%233.33%
andrew mortonandrew morton59.80%116.67%
cornelia huckcornelia huck11.96%116.67%
Total51100.00%6100.00%


static void __exit cleanup_ccwgroup(void) { bus_unregister_notifier(&ccwgroup_bus_type, &ccwgroup_nb); bus_unregister(&ccwgroup_bus_type); }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott2083.33%150.00%
martin schwidefskymartin schwidefsky416.67%150.00%
Total24100.00%2100.00%

module_init(init_ccwgroup); module_exit(cleanup_ccwgroup); /************************** driver stuff ******************************/
static int ccwgroup_remove(struct device *dev) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); if (!dev->driver) return 0; if (gdrv->remove) gdrv->remove(gdev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
martin schwidefskymartin schwidefsky3355.93%125.00%
sebastian ottsebastian ott2237.29%250.00%
andrew mortonandrew morton46.78%125.00%
Total59100.00%4100.00%


static void ccwgroup_shutdown(struct device *dev) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); if (!dev->driver) return; if (gdrv->shutdown) gdrv->shutdown(gdev); }

Contributors

PersonTokensPropCommitsCommitProp
cornelia huckcornelia huck3462.96%133.33%
sebastian ottsebastian ott2037.04%266.67%
Total54100.00%3100.00%


static int ccwgroup_pm_prepare(struct device *dev) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); /* Fail while device is being set online/offline. */ if (atomic_read(&gdev->onoff)) return -EAGAIN; if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) return 0; return gdrv->prepare ? gdrv->prepare(gdev) : 0; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott82100.00%1100.00%
Total82100.00%1100.00%


static void ccwgroup_pm_complete(struct device *dev) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) return; if (gdrv->complete) gdrv->complete(gdev); }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott62100.00%1100.00%
Total62100.00%1100.00%


static int ccwgroup_pm_freeze(struct device *dev) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) return 0; return gdrv->freeze ? gdrv->freeze(gdev) : 0; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott67100.00%1100.00%
Total67100.00%1100.00%


static int ccwgroup_pm_thaw(struct device *dev) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) return 0; return gdrv->thaw ? gdrv->thaw(gdev) : 0; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott67100.00%1100.00%
Total67100.00%1100.00%


static int ccwgroup_pm_restore(struct device *dev) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver); if (!gdev->dev.driver || gdev->state != CCWGROUP_ONLINE) return 0; return gdrv->restore ? gdrv->restore(gdev) : 0; }

Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott67100.00%1100.00%
Total67100.00%1100.00%

static const struct dev_pm_ops ccwgroup_pm_ops = { .prepare = ccwgroup_pm_prepare, .complete = ccwgroup_pm_complete, .freeze = ccwgroup_pm_freeze, .thaw = ccwgroup_pm_thaw, .restore = ccwgroup_pm_restore, }; static struct bus_type ccwgroup_bus_type = { .name = "ccwgroup", .remove = ccwgroup_remove, .shutdown = ccwgroup_shutdown, .pm = &ccwgroup_pm_ops, }; /** * ccwgroup_driver_register() - register a ccw group driver * @cdriver: driver to be registered * * This function is mainly a wrapper around driver_register(). */
int ccwgroup_driver_register(struct ccwgroup_driver *cdriver) { /* register our new driver with the core */ cdriver->driver.bus = &ccwgroup_bus_type; return driver_register(&cdriver->driver); }

Contributors

PersonTokensPropCommitsCommitProp
martin schwidefskymartin schwidefsky2793.10%133.33%
heiko carstensheiko carstens13.45%133.33%
cornelia huckcornelia huck13.45%133.33%
Total29100.00%3100.00%

EXPORT_SYMBOL(ccwgroup_driver_register);
static int __ccwgroup_match_all(struct device *dev, void *data) { return 1; }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton1055.56%133.33%
cornelia huckcornelia huck844.44%266.67%
Total18100.00%3100.00%

/** * ccwgroup_driver_unregister() - deregister a ccw group driver * @cdriver: driver to be deregistered * * This function is mainly a wrapper around driver_unregister(). */
void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) { struct device *dev; /* We don't want ccwgroup devices to live longer than their driver. */ while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, __ccwgroup_match_all))) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); ccwgroup_ungroup(gdev); put_device(dev); } driver_unregister(&cdriver->driver); }

Contributors

PersonTokensPropCommitsCommitProp
cornelia huckcornelia huck4263.64%457.14%
martin schwidefskymartin schwidefsky1725.76%114.29%
andrew mortonandrew morton69.09%114.29%
sebastian ottsebastian ott11.52%114.29%
Total66100.00%7100.00%

EXPORT_SYMBOL(ccwgroup_driver_unregister); /** * ccwgroup_probe_ccwdev() - probe function for slave devices * @cdev: ccw device to be probed * * This is a dummy probe function for ccw devices that are slave devices in * a ccw group device. * Returns: * always %0 */
int ccwgroup_probe_ccwdev(struct ccw_device *cdev) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
martin schwidefskymartin schwidefsky1292.31%150.00%
cornelia huckcornelia huck17.69%150.00%
Total13100.00%2100.00%

EXPORT_SYMBOL(ccwgroup_probe_ccwdev); /** * ccwgroup_remove_ccwdev() - remove function for slave devices * @cdev: ccw device to be removed * * This is a remove function for ccw devices that are slave devices in a ccw * group device. It sets the ccw device offline and also deregisters the * embedding ccw group device. */
void ccwgroup_remove_ccwdev(struct ccw_device *cdev) { struct ccwgroup_device *gdev; /* Ignore offlining errors, device is gone anyway. */ ccw_device_set_offline(cdev); /* If one of its devices is gone, the whole group is done for. */ spin_lock_irq(cdev->ccwlock); gdev = dev_get_drvdata(&cdev->dev); if (!gdev) { spin_unlock_irq(cdev->ccwlock); return; } /* Get ccwgroup device reference for local processing. */ get_device(&gdev->dev); spin_unlock_irq(cdev->ccwlock); /* Unregister group device. */ ccwgroup_ungroup(gdev); /* Release ccwgroup device reference for local processing. */ put_device(&gdev->dev); }

Contributors

PersonTokensPropCommitsCommitProp
peter oberparleiterpeter oberparleiter3237.65%114.29%
martin schwidefskymartin schwidefsky2934.12%114.29%
cornelia huckcornelia huck1720.00%228.57%
andrew mortonandrew morton67.06%228.57%
sebastian ottsebastian ott11.18%114.29%
Total85100.00%7100.00%

EXPORT_SYMBOL(ccwgroup_remove_ccwdev); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
sebastian ottsebastian ott145950.43%1531.25%
martin schwidefskymartin schwidefsky70124.23%36.25%
peter oberparleiterpeter oberparleiter2067.12%36.25%
cornelia huckcornelia huck1725.95%1122.92%
ursula braun-krahlursula braun-krahl1414.87%12.08%
andrew mortonandrew morton983.39%612.50%
tejun heotejun heo662.28%12.08%
alan sternalan stern240.83%12.08%
russell kingrussell king170.59%12.08%
kay sieverskay sievers40.14%12.08%
jingoo hanjingoo han10.03%12.08%
heiko carstensheiko carstens10.03%12.08%
yani ioannouyani ioannou10.03%12.08%
alexey dobriyanalexey dobriyan10.03%12.08%
eric sesterhenneric sesterhenn10.03%12.08%
Total2893100.00%48100.00%
Directory: drivers/s390/cio
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}