+static ssize_t
+remove_write (struct device_driver *drv, const char *buf, size_t count)
+{
+ struct iucv_connection **clist = &iucv_conns.iucv_connections;
+ unsigned long flags;
+ struct net_device *ndev;
+ struct netiucv_priv *priv;
+ struct device *dev;
+ char name[IFNAMSIZ];
+ char *p;
+ int i;
+
+ IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+
+ if (count >= IFNAMSIZ)
+ count = IFNAMSIZ - 1;;
+
+ for (i=0, p=(char *)buf; i<count && *p; i++, p++) {
+ if ((*p == '\n') || (*p == ' ')) {
+ /* trailing lf, grr */
+ break;
+ } else {
+ name[i]=*p;
+ }
+ }
+ name[i] = '\0';
+
+ read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
+ while (*clist) {
+ ndev = (*clist)->netdev;
+ priv = (struct netiucv_priv*)ndev->priv;
+ dev = priv->dev;
+
+ if (strncmp(name, ndev->name, count)) {
+ clist = &((*clist)->next);
+ continue;
+ }
+ read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+ if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
+ PRINT_WARN(
+ "netiucv: net device %s active with peer %s\n",
+ ndev->name, priv->conn->userid);
+ PRINT_WARN("netiucv: %s cannot be removed\n",
+ ndev->name);
+ IUCV_DBF_TEXT(data, 2, "remove_write: still active\n");
+ return -EBUSY;
+ }
+ unregister_netdev(ndev);
+ netiucv_unregister_device(dev);
+ return count;
+ }
+ read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+ PRINT_WARN("netiucv: net device %s unknown\n", name);
+ IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n");
+ return -EINVAL;
+}
+
+DRIVER_ATTR(remove, 0200, NULL, remove_write);