]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/ethernet/ibm/ibmvnic.c
ibmvnic: Fix non-atomic memory allocation in IRQ context
[linux.git] / drivers / net / ethernet / ibm / ibmvnic.c
index c0203a0d5e3b8be87f33a7eb7a1f11b1ecd8ca18..67cc6d9c8fd7257af3e3c592fd96a636cc8be326 100644 (file)
@@ -1859,7 +1859,7 @@ static int do_reset(struct ibmvnic_adapter *adapter,
 
        if (adapter->reset_reason != VNIC_RESET_FAILOVER &&
            adapter->reset_reason != VNIC_RESET_CHANGE_PARAM)
-               netdev_notify_peers(netdev);
+               call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev);
 
        netif_carrier_on(netdev);
 
@@ -1939,8 +1939,9 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,
 static struct ibmvnic_rwi *get_next_rwi(struct ibmvnic_adapter *adapter)
 {
        struct ibmvnic_rwi *rwi;
+       unsigned long flags;
 
-       mutex_lock(&adapter->rwi_lock);
+       spin_lock_irqsave(&adapter->rwi_lock, flags);
 
        if (!list_empty(&adapter->rwi_list)) {
                rwi = list_first_entry(&adapter->rwi_list, struct ibmvnic_rwi,
@@ -1950,7 +1951,7 @@ static struct ibmvnic_rwi *get_next_rwi(struct ibmvnic_adapter *adapter)
                rwi = NULL;
        }
 
-       mutex_unlock(&adapter->rwi_lock);
+       spin_unlock_irqrestore(&adapter->rwi_lock, flags);
        return rwi;
 }
 
@@ -2025,6 +2026,7 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
        struct list_head *entry, *tmp_entry;
        struct ibmvnic_rwi *rwi, *tmp;
        struct net_device *netdev = adapter->netdev;
+       unsigned long flags;
        int ret;
 
        if (adapter->state == VNIC_REMOVING ||
@@ -2041,21 +2043,21 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
                goto err;
        }
 
-       mutex_lock(&adapter->rwi_lock);
+       spin_lock_irqsave(&adapter->rwi_lock, flags);
 
        list_for_each(entry, &adapter->rwi_list) {
                tmp = list_entry(entry, struct ibmvnic_rwi, list);
                if (tmp->reset_reason == reason) {
                        netdev_dbg(netdev, "Skipping matching reset\n");
-                       mutex_unlock(&adapter->rwi_lock);
+                       spin_unlock_irqrestore(&adapter->rwi_lock, flags);
                        ret = EBUSY;
                        goto err;
                }
        }
 
-       rwi = kzalloc(sizeof(*rwi), GFP_KERNEL);
+       rwi = kzalloc(sizeof(*rwi), GFP_ATOMIC);
        if (!rwi) {
-               mutex_unlock(&adapter->rwi_lock);
+               spin_unlock_irqrestore(&adapter->rwi_lock, flags);
                ibmvnic_close(netdev);
                ret = ENOMEM;
                goto err;
@@ -2069,7 +2071,7 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
        }
        rwi->reset_reason = reason;
        list_add_tail(&rwi->list, &adapter->rwi_list);
-       mutex_unlock(&adapter->rwi_lock);
+       spin_unlock_irqrestore(&adapter->rwi_lock, flags);
        adapter->resetting = true;
        netdev_dbg(adapter->netdev, "Scheduling reset (reason %d)\n", reason);
        schedule_work(&adapter->ibmvnic_reset);
@@ -4759,7 +4761,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
 
        INIT_WORK(&adapter->ibmvnic_reset, __ibmvnic_reset);
        INIT_LIST_HEAD(&adapter->rwi_list);
-       mutex_init(&adapter->rwi_lock);
+       spin_lock_init(&adapter->rwi_lock);
        adapter->resetting = false;
 
        adapter->mac_change_pending = false;