diff options
Diffstat (limited to 'drivers/net/ehea/ehea_main.c')
-rw-r--r-- | drivers/net/ehea/ehea_main.c | 78 |
1 files changed, 52 insertions, 26 deletions
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 809ccc9ff09..02698a1c80b 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -791,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)) @@ -814,7 +820,7 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota) quota--; cqe = ehea_poll_cq(send_cq); - }; + } ehea_update_feca(send_cq, cqe_counter); atomic_add(swqe_av, &pr->swqe_avail); @@ -901,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); @@ -910,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; } @@ -1618,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 */ @@ -1629,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 */ @@ -1651,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; @@ -1860,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, @@ -1967,7 +1987,7 @@ 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; + struct netdev_hw_addr *ha; int ret; if (dev->flags & IFF_PROMISC) { @@ -1998,13 +2018,12 @@ static void ehea_set_multicast_list(struct net_device *dev) goto out; } - netdev_for_each_mc_addr(k_mcl_entry, dev) - 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; } @@ -3238,7 +3253,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter) ehea_remove_adapter_mr(adapter); i++; - }; + } return 0; } @@ -3257,7 +3272,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter, if (dn_log_port_id) if (*dn_log_port_id == logical_port_id) return eth_dn; - }; + } return NULL; } @@ -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 = { |