- Update to 3.4-rc7.
[linux-flexiantxendom0-3.2.10.git] / drivers / net / ethernet / ibm / ehea / ehea_main.c
index bfd08b2..e44d164 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/net/ehea/ehea_main.c
+ *  linux/drivers/net/ethernet/ibm/ehea/ehea_main.c
  *
  *  eHEA ethernet device driver for IBM eServer System p
  *
@@ -94,8 +94,8 @@ static int port_name_cnt;
 static LIST_HEAD(adapter_list);
 static unsigned long ehea_driver_flags;
 static DEFINE_MUTEX(dlpar_mem_lock);
-struct ehea_fw_handle_array ehea_fw_handles;
-struct ehea_bcmc_reg_array ehea_bcmc_regs;
+static struct ehea_fw_handle_array ehea_fw_handles;
+static struct ehea_bcmc_reg_array ehea_bcmc_regs;
 
 
 static int __devinit ehea_probe_adapter(struct platform_device *dev,
@@ -103,6 +103,19 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
 
 static int __devexit ehea_remove(struct platform_device *dev);
 
+static struct of_device_id ehea_module_device_table[] = {
+       {
+               .name = "lhea",
+               .compatible = "IBM,lhea",
+       },
+       {
+               .type = "network",
+               .compatible = "IBM,lhea-ethernet",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ehea_module_device_table);
+
 static struct of_device_id ehea_device_table[] = {
        {
                .name = "lhea",
@@ -110,7 +123,6 @@ static struct of_device_id ehea_device_table[] = {
        },
        {},
 };
-MODULE_DEVICE_TABLE(of, ehea_device_table);
 
 static struct of_platform_driver ehea_driver = {
        .driver = {
@@ -133,7 +145,7 @@ void ehea_dump(void *adr, int len, char *msg)
        }
 }
 
-void ehea_schedule_port_reset(struct ehea_port *port)
+static void ehea_schedule_port_reset(struct ehea_port *port)
 {
        if (!test_bit(__EHEA_DISABLE_PORT_RESET, &port->flags))
                schedule_work(&port->reset_task);
@@ -290,16 +302,18 @@ static void ehea_update_bcmc_registrations(void)
 
                                arr[i].adh = adapter->handle;
                                arr[i].port_id = port->logical_port_id;
-                               arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
-                                                 EHEA_BCMC_MULTICAST |
+                               arr[i].reg_type = EHEA_BCMC_MULTICAST |
                                                  EHEA_BCMC_UNTAGGED;
+                               if (mc_entry->macaddr == 0)
+                                       arr[i].reg_type |= EHEA_BCMC_SCOPE_ALL;
                                arr[i++].macaddr = mc_entry->macaddr;
 
                                arr[i].adh = adapter->handle;
                                arr[i].port_id = port->logical_port_id;
-                               arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
-                                                 EHEA_BCMC_MULTICAST |
+                               arr[i].reg_type = EHEA_BCMC_MULTICAST |
                                                  EHEA_BCMC_VLANID_ALL;
+                               if (mc_entry->macaddr == 0)
+                                       arr[i].reg_type |= EHEA_BCMC_SCOPE_ALL;
                                arr[i++].macaddr = mc_entry->macaddr;
                                num_registrations -= 2;
                        }
@@ -336,7 +350,9 @@ static struct rtnl_link_stats64 *ehea_get_stats64(struct net_device *dev,
        stats->tx_bytes = tx_bytes;
        stats->rx_packets = rx_packets;
 
-       return &port->stats;
+       stats->multicast = port->stats.multicast;
+       stats->rx_errors = port->stats.rx_errors;
+       return stats;
 }
 
 static void ehea_update_stats(struct work_struct *work)
@@ -371,7 +387,8 @@ static void ehea_update_stats(struct work_struct *work)
 out_herr:
        free_page((unsigned long)cb2);
 resched:
-       schedule_delayed_work(&port->stats_work, msecs_to_jiffies(1000));
+       schedule_delayed_work(&port->stats_work,
+                             round_jiffies_relative(msecs_to_jiffies(1000)));
 }
 
 static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
@@ -1403,7 +1420,7 @@ out:
        return ret;
 }
 
-int ehea_gen_smrs(struct ehea_port_res *pr)
+static int ehea_gen_smrs(struct ehea_port_res *pr)
 {
        int ret;
        struct ehea_adapter *adapter = pr->port->adapter;
@@ -1425,7 +1442,7 @@ out:
        return -EIO;
 }
 
-int ehea_rem_smrs(struct ehea_port_res *pr)
+static int ehea_rem_smrs(struct ehea_port_res *pr)
 {
        if ((ehea_rem_mr(&pr->send_mr)) ||
            (ehea_rem_mr(&pr->recv_mr)))
@@ -1676,7 +1693,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
 
                        /* copy sg1entry data */
                        sg1entry->l_key = lkey;
-                       sg1entry->len = frag->size;
+                       sg1entry->len = skb_frag_size(frag);
                        sg1entry->vaddr =
                                ehea_map_vaddr(skb_frag_address(frag));
                        swqe->descriptors++;
@@ -1689,7 +1706,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
                        sgentry = &sg_list[i - sg1entry_contains_frag_data];
 
                        sgentry->l_key = lkey;
-                       sgentry->len = frag->size;
+                       sgentry->len = skb_frag_size(frag);
                        sgentry->vaddr = ehea_map_vaddr(skb_frag_address(frag));
                        swqe->descriptors++;
                }
@@ -1835,8 +1852,9 @@ static u64 ehea_multicast_reg_helper(struct ehea_port *port, u64 mc_mac_addr,
        u64 hret;
        u8 reg_type;
 
-       reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
-                | EHEA_BCMC_UNTAGGED;
+       reg_type = EHEA_BCMC_MULTICAST | EHEA_BCMC_UNTAGGED;
+       if (mc_mac_addr == 0)
+               reg_type |= EHEA_BCMC_SCOPE_ALL;
 
        hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
                                     port->logical_port_id,
@@ -1844,8 +1862,9 @@ static u64 ehea_multicast_reg_helper(struct ehea_port *port, u64 mc_mac_addr,
        if (hret)
                goto out;
 
-       reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
-                | EHEA_BCMC_VLANID_ALL;
+       reg_type = EHEA_BCMC_MULTICAST | EHEA_BCMC_VLANID_ALL;
+       if (mc_mac_addr == 0)
+               reg_type |= EHEA_BCMC_SCOPE_ALL;
 
        hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
                                     port->logical_port_id,
@@ -1895,7 +1914,7 @@ static void ehea_allmulti(struct net_device *dev, int enable)
                                netdev_err(dev,
                                           "failed enabling IFF_ALLMULTI\n");
                }
-       } else
+       } else {
                if (!enable) {
                        /* Disable ALLMULTI */
                        hret = ehea_multicast_reg_helper(port, 0, H_DEREG_BCMC);
@@ -1905,6 +1924,7 @@ static void ehea_allmulti(struct net_device *dev, int enable)
                                netdev_err(dev,
                                           "failed disabling IFF_ALLMULTI\n");
                }
+       }
 }
 
 static void ehea_add_multicast_entry(struct ehea_port *port, u8 *mc_mac_addr)
@@ -1938,11 +1958,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
        struct netdev_hw_addr *ha;
        int ret;
 
-       if (port->promisc) {
-               ehea_promiscuous(dev, 1);
-               return;
-       }
-       ehea_promiscuous(dev, 0);
+       ehea_promiscuous(dev, !!(dev->flags & IFF_PROMISC));
 
        if (dev->flags & IFF_ALLMULTI) {
                ehea_allmulti(dev, 1);
@@ -2001,7 +2017,6 @@ static void xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe)
 
                swqe->tcp_offset = swqe->ip_end + 1 +
                                   offsetof(struct udphdr, check);
-               swqe->tcp_end = skb->len - 1;
                break;
 
        case IPPROTO_TCP:
@@ -2010,7 +2025,6 @@ static void xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe)
 
                swqe->tcp_offset = swqe->ip_end + 1 +
                                   offsetof(struct tcphdr, check);
-               swqe->tcp_end = skb->len - 1;
                break;
        }
 }
@@ -2115,17 +2129,19 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+static int ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
        struct ehea_port *port = netdev_priv(dev);
        struct ehea_adapter *adapter = port->adapter;
        struct hcp_ehea_port_cb1 *cb1;
        int index;
        u64 hret;
+       int err = 0;
 
        cb1 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb1) {
                pr_err("no mem for cb1\n");
+               err = -ENOMEM;
                goto out;
        }
 
@@ -2133,6 +2149,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
                                      H_PORT_CB1, H_PORT_CB1_ALL, cb1);
        if (hret != H_SUCCESS) {
                pr_err("query_ehea_port failed\n");
+               err = -EINVAL;
                goto out;
        }
 
@@ -2141,24 +2158,28 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 
        hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
                                       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
-       if (hret != H_SUCCESS)
+       if (hret != H_SUCCESS) {
                pr_err("modify_ehea_port failed\n");
+               err = -EINVAL;
+       }
 out:
        free_page((unsigned long)cb1);
-       return;
+       return err;
 }
 
-static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+static int ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
        struct ehea_port *port = netdev_priv(dev);
        struct ehea_adapter *adapter = port->adapter;
        struct hcp_ehea_port_cb1 *cb1;
        int index;
        u64 hret;
+       int err = 0;
 
        cb1 = (void *)get_zeroed_page(GFP_KERNEL);
        if (!cb1) {
                pr_err("no mem for cb1\n");
+               err = -ENOMEM;
                goto out;
        }
 
@@ -2166,6 +2187,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
                                      H_PORT_CB1, H_PORT_CB1_ALL, cb1);
        if (hret != H_SUCCESS) {
                pr_err("query_ehea_port failed\n");
+               err = -EINVAL;
                goto out;
        }
 
@@ -2174,13 +2196,16 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 
        hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
                                       H_PORT_CB1, H_PORT_CB1_ALL, cb1);
-       if (hret != H_SUCCESS)
+       if (hret != H_SUCCESS) {
                pr_err("modify_ehea_port failed\n");
+               err = -EINVAL;
+       }
 out:
        free_page((unsigned long)cb1);
+       return err;
 }
 
-int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
+static int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
 {
        int ret = -EIO;
        u64 hret;
@@ -2436,7 +2461,8 @@ static int ehea_open(struct net_device *dev)
        }
 
        mutex_unlock(&port->port_lock);
-       schedule_delayed_work(&port->stats_work, msecs_to_jiffies(1000));
+       schedule_delayed_work(&port->stats_work,
+                             round_jiffies_relative(msecs_to_jiffies(1000)));
 
        return ret;
 }
@@ -2450,6 +2476,7 @@ static int ehea_down(struct net_device *dev)
                return 0;
 
        ehea_drop_multicast_list(dev);
+       ehea_allmulti(dev, 0);
        ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
 
        ehea_free_interrupts(dev);
@@ -2520,7 +2547,7 @@ static void ehea_flush_sq(struct ehea_port *port)
        }
 }
 
-int ehea_stop_qps(struct net_device *dev)
+static int ehea_stop_qps(struct net_device *dev)
 {
        struct ehea_port *port = netdev_priv(dev);
        struct ehea_adapter *adapter = port->adapter;
@@ -2589,7 +2616,7 @@ out:
        return ret;
 }
 
-void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
+static void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
 {
        struct ehea_qp qp = *orig_qp;
        struct ehea_qp_init_attr *init_attr = &qp.init_attr;
@@ -2622,7 +2649,7 @@ void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
        }
 }
 
-int ehea_restart_qps(struct net_device *dev)
+static int ehea_restart_qps(struct net_device *dev)
 {
        struct ehea_port *port = netdev_priv(dev);
        struct ehea_adapter *adapter = port->adapter;
@@ -2813,7 +2840,7 @@ static void ehea_tx_watchdog(struct net_device *dev)
                ehea_schedule_port_reset(port);
 }
 
-int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
+static int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
 {
        struct hcp_query_ehea *cb;
        u64 hret;
@@ -2841,7 +2868,7 @@ out:
        return ret;
 }
 
-int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
+static int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
 {
        struct hcp_ehea_port_cb4 *cb4;
        u64 hret;
@@ -2955,7 +2982,7 @@ static const struct net_device_ops ehea_netdev_ops = {
        .ndo_tx_timeout         = ehea_tx_watchdog,
 };
 
-struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
+static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
                                         u32 logical_port_id,
                                         struct device_node *dn)
 {
@@ -2969,7 +2996,6 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
        dev = alloc_etherdev_mq(sizeof(struct ehea_port), EHEA_MAX_PORT_RES);
 
        if (!dev) {
-               pr_err("no mem for net_device\n");
                ret = -ENOMEM;
                goto out_err;
        }
@@ -3226,7 +3252,7 @@ static ssize_t ehea_remove_port(struct device *dev,
 static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
 static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
 
-int ehea_create_device_sysfs(struct platform_device *dev)
+static int ehea_create_device_sysfs(struct platform_device *dev)
 {
        int ret = device_create_file(&dev->dev, &dev_attr_probe_port);
        if (ret)
@@ -3237,7 +3263,7 @@ out:
        return ret;
 }
 
-void ehea_remove_device_sysfs(struct platform_device *dev)
+static void ehea_remove_device_sysfs(struct platform_device *dev)
 {
        device_remove_file(&dev->dev, &dev_attr_probe_port);
        device_remove_file(&dev->dev, &dev_attr_remove_port);
@@ -3249,6 +3275,7 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
        struct ehea_adapter *adapter;
        const u64 *adapter_handle;
        int ret;
+       int i;
 
        if (!dev || !dev->dev.of_node) {
                pr_err("Invalid ibmebus device probed\n");
@@ -3302,17 +3329,9 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
        tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
                     (unsigned long)adapter);
 
-       ret = ibmebus_request_irq(adapter->neq->attr.ist1,
-                                 ehea_interrupt_neq, IRQF_DISABLED,
-                                 "ehea_neq", adapter);
-       if (ret) {
-               dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
-               goto out_kill_eq;
-       }
-
        ret = ehea_create_device_sysfs(dev);
        if (ret)
-               goto out_free_irq;
+               goto out_kill_eq;
 
        ret = ehea_setup_ports(adapter);
        if (ret) {
@@ -3320,15 +3339,30 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
                goto out_rem_dev_sysfs;
        }
 
+       ret = ibmebus_request_irq(adapter->neq->attr.ist1,
+                                 ehea_interrupt_neq, IRQF_DISABLED,
+                                 "ehea_neq", adapter);
+       if (ret) {
+               dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
+               goto out_shutdown_ports;
+       }
+
+       /* Handle any events that might be pending. */
+       tasklet_hi_schedule(&adapter->neq_tasklet);
+
        ret = 0;
        goto out;
 
+out_shutdown_ports:
+       for (i = 0; i < EHEA_MAX_PORTS; i++)
+               if (adapter->port[i]) {
+                       ehea_shutdown_single_port(adapter->port[i]);
+                       adapter->port[i] = NULL;
+               }
+
 out_rem_dev_sysfs:
        ehea_remove_device_sysfs(dev);
 
-out_free_irq:
-       ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
-
 out_kill_eq:
        ehea_destroy_eq(adapter->neq);
 
@@ -3368,7 +3402,7 @@ static int __devexit ehea_remove(struct platform_device *dev)
        return 0;
 }
 
-void ehea_crash_handler(void)
+static void ehea_crash_handler(void)
 {
        int i;
 
@@ -3480,7 +3514,7 @@ static ssize_t ehea_show_capabilities(struct device_driver *drv,
 static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
                   ehea_show_capabilities, NULL);
 
-int __init ehea_module_init(void)
+static int __init ehea_module_init(void)
 {
        int ret;