Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/inaky/wimax
[firefly-linux-kernel-4.4.55.git] / drivers / net / ehea / ehea_main.c
index 7b62336e6736177ede8ae77789a5c82ed406222f..e8a8ccfedac638c65ccd187c39272a75f9967cf7 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/udp.h>
 #include <linux/if.h>
 #include <linux/list.h>
+#include <linux/slab.h>
 #include <linux/if_ether.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
@@ -790,11 +791,17 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
                cqe_counter++;
                rmb();
                if (cqe->status & EHEA_CQE_STAT_ERR_MASK) {
-                       ehea_error("Send Completion Error: Resetting port");
+                       ehea_error("Bad send completion status=0x%04X",
+                                  cqe->status);
+
                        if (netif_msg_tx_err(pr->port))
                                ehea_dump(cqe, sizeof(*cqe), "Send CQE");
-                       ehea_schedule_port_reset(pr->port);
-                       break;
+
+                       if (cqe->status & EHEA_CQE_STAT_RESET_MASK) {
+                               ehea_error("Resetting port");
+                               ehea_schedule_port_reset(pr->port);
+                               break;
+                       }
                }
 
                if (netif_msg_tx_done(pr->port))
@@ -900,6 +907,8 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
        struct ehea_eqe *eqe;
        struct ehea_qp *qp;
        u32 qp_token;
+       u64 resource_type, aer, aerr;
+       int reset_port = 0;
 
        eqe = ehea_poll_eq(port->qp_eq);
 
@@ -909,11 +918,24 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
                           eqe->entry, qp_token);
 
                qp = port->port_res[qp_token].qp;
-               ehea_error_data(port->adapter, qp->fw_handle);
+
+               resource_type = ehea_error_data(port->adapter, qp->fw_handle,
+                                               &aer, &aerr);
+
+               if (resource_type == EHEA_AER_RESTYPE_QP) {
+                       if ((aer & EHEA_AER_RESET_MASK) ||
+                           (aerr & EHEA_AERR_RESET_MASK))
+                                reset_port = 1;
+               } else
+                       reset_port = 1;   /* Reset in case of CQ or EQ error */
+
                eqe = ehea_poll_eq(port->qp_eq);
        }
 
-       ehea_schedule_port_reset(port);
+       if (reset_port) {
+               ehea_error("Resetting port");
+               ehea_schedule_port_reset(port);
+       }
 
        return IRQ_HANDLED;
 }
@@ -1617,7 +1639,7 @@ static void write_swqe2_TSO(struct sk_buff *skb,
 {
        struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
        u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
-       int skb_data_size = skb->len - skb->data_len;
+       int skb_data_size = skb_headlen(skb);
        int headersize;
 
        /* Packet is TCP with TSO enabled */
@@ -1628,7 +1650,7 @@ static void write_swqe2_TSO(struct sk_buff *skb,
         */
        headersize = ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
 
-       skb_data_size = skb->len - skb->data_len;
+       skb_data_size = skb_headlen(skb);
 
        if (skb_data_size >= headersize) {
                /* copy immediate data */
@@ -1650,7 +1672,7 @@ static void write_swqe2_TSO(struct sk_buff *skb,
 static void write_swqe2_nonTSO(struct sk_buff *skb,
                               struct ehea_swqe *swqe, u32 lkey)
 {
-       int skb_data_size = skb->len - skb->data_len;
+       int skb_data_size = skb_headlen(skb);
        u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
        struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
 
@@ -1859,7 +1881,6 @@ static void ehea_promiscuous(struct net_device *dev, int enable)
        port->promisc = enable;
 out:
        free_page((unsigned long)cb7);
-       return;
 }
 
 static u64 ehea_multicast_reg_helper(struct ehea_port *port, u64 mc_mac_addr,
@@ -1966,8 +1987,8 @@ static void ehea_add_multicast_entry(struct ehea_port *port, u8 *mc_mac_addr)
 static void ehea_set_multicast_list(struct net_device *dev)
 {
        struct ehea_port *port = netdev_priv(dev);
-       struct dev_mc_list *k_mcl_entry;
-       int ret, i;
+       struct netdev_hw_addr *ha;
+       int ret;
 
        if (dev->flags & IFF_PROMISC) {
                ehea_promiscuous(dev, 1);
@@ -1981,7 +2002,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
        }
        ehea_allmulti(dev, 0);
 
-       if (dev->mc_count) {
+       if (!netdev_mc_empty(dev)) {
                ret = ehea_drop_multicast_list(dev);
                if (ret) {
                        /* Dropping the current multicast list failed.
@@ -1990,21 +2011,19 @@ static void ehea_set_multicast_list(struct net_device *dev)
                        ehea_allmulti(dev, 1);
                }
 
-               if (dev->mc_count > port->adapter->max_mc_mac) {
+               if (netdev_mc_count(dev) > port->adapter->max_mc_mac) {
                        ehea_info("Mcast registration limit reached (0x%llx). "
                                  "Use ALLMULTI!",
                                  port->adapter->max_mc_mac);
                        goto out;
                }
 
-               for (i = 0, k_mcl_entry = dev->mc_list; i < dev->mc_count; i++,
-                            k_mcl_entry = k_mcl_entry->next)
-                       ehea_add_multicast_entry(port, k_mcl_entry->dmi_addr);
+               netdev_for_each_mc_addr(ha, dev)
+                       ehea_add_multicast_entry(port, ha->addr);
 
        }
 out:
        ehea_update_bcmc_registrations();
-       return;
 }
 
 static int ehea_change_mtu(struct net_device *dev, int new_mtu)
@@ -2108,8 +2127,8 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
        } else {
                /* first copy data from the skb->data buffer ... */
                skb_copy_from_linear_data(skb, imm_data,
-                                         skb->len - skb->data_len);
-               imm_data += skb->len - skb->data_len;
+                                         skb_headlen(skb));
+               imm_data += skb_headlen(skb);
 
                /* ... then copy data from the fragments */
                for (i = 0; i < nfrags; i++) {
@@ -2220,7 +2239,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
                spin_unlock_irqrestore(&pr->netif_queue, flags);
        }
-       dev->trans_start = jiffies;
+       dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
        spin_unlock(&pr->xmit_lock);
 
        return NETDEV_TX_OK;
@@ -2317,7 +2336,6 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
                ehea_error("modify_ehea_port failed");
 out:
        free_page((unsigned long)cb1);
-       return;
 }
 
 int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
@@ -2860,7 +2878,6 @@ static void ehea_reset_port(struct work_struct *work)
        netif_wake_queue(dev);
 out:
        mutex_unlock(&port->port_lock);
-       return;
 }
 
 static void ehea_rereg_mrs(struct work_struct *work)
@@ -2868,7 +2885,6 @@ static void ehea_rereg_mrs(struct work_struct *work)
        int ret, i;
        struct ehea_adapter *adapter;
 
-       mutex_lock(&dlpar_mem_lock);
        ehea_info("LPAR memory changed - re-initializing driver");
 
        list_for_each_entry(adapter, &adapter_list, list)
@@ -2938,7 +2954,6 @@ static void ehea_rereg_mrs(struct work_struct *work)
                }
        ehea_info("re-initializing driver complete");
 out:
-       mutex_unlock(&dlpar_mem_lock);
        return;
 }
 
@@ -3521,7 +3536,14 @@ void ehea_crash_handler(void)
 static int ehea_mem_notifier(struct notifier_block *nb,
                              unsigned long action, void *data)
 {
+       int ret = NOTIFY_BAD;
        struct memory_notify *arg = data;
+
+       if (!mutex_trylock(&dlpar_mem_lock)) {
+               ehea_info("ehea_mem_notifier must not be called parallelized");
+               goto out;
+       }
+
        switch (action) {
        case MEM_CANCEL_OFFLINE:
                ehea_info("memory offlining canceled");
@@ -3530,14 +3552,14 @@ static int ehea_mem_notifier(struct notifier_block *nb,
                ehea_info("memory is going online");
                set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
                if (ehea_add_sect_bmap(arg->start_pfn, arg->nr_pages))
-                       return NOTIFY_BAD;
+                       goto out_unlock;
                ehea_rereg_mrs(NULL);
                break;
        case MEM_GOING_OFFLINE:
                ehea_info("memory is going offline");
                set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
                if (ehea_rem_sect_bmap(arg->start_pfn, arg->nr_pages))
-                       return NOTIFY_BAD;
+                       goto out_unlock;
                ehea_rereg_mrs(NULL);
                break;
        default:
@@ -3545,8 +3567,12 @@ static int ehea_mem_notifier(struct notifier_block *nb,
        }
 
        ehea_update_firmware_handles();
+       ret = NOTIFY_OK;
 
-       return NOTIFY_OK;
+out_unlock:
+       mutex_unlock(&dlpar_mem_lock);
+out:
+       return ret;
 }
 
 static struct notifier_block ehea_mem_nb = {