Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
[linux-2.6.git] / drivers / net / ps3_gelic_net.c
index 4b564ed..89c4948 100644 (file)
@@ -95,11 +95,11 @@ static void gelic_card_get_ether_port_status(struct gelic_card *card,
 
        lv1_net_control(bus_id(card), dev_id(card),
                        GELIC_LV1_GET_ETH_PORT_STATUS,
-                       GELIC_LV1_VLAN_TX_ETHERNET, 0, 0,
+                       GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0,
                        &card->ether_port_status, &v2);
 
        if (inform) {
-               ether_netdev = card->netdev[GELIC_PORT_ETHERNET];
+               ether_netdev = card->netdev[GELIC_PORT_ETHERNET_0];
                if (card->ether_port_status & GELIC_LV1_ETHER_LINK_UP)
                        netif_carrier_on(ether_netdev);
                else
@@ -107,6 +107,24 @@ static void gelic_card_get_ether_port_status(struct gelic_card *card,
        }
 }
 
+static int gelic_card_set_link_mode(struct gelic_card *card, int mode)
+{
+       int status;
+       u64 v1, v2;
+
+       status = lv1_net_control(bus_id(card), dev_id(card),
+                                GELIC_LV1_SET_NEGOTIATION_MODE,
+                                GELIC_LV1_PHY_ETHERNET_0, mode, 0, &v1, &v2);
+       if (status) {
+               pr_info("%s: failed setting negotiation mode %d\n", __func__,
+                       status);
+               return -EBUSY;
+       }
+
+       card->link_mode = mode;
+       return 0;
+}
+
 void gelic_card_up(struct gelic_card *card)
 {
        pr_debug("%s: called\n", __func__);
@@ -214,9 +232,10 @@ static void gelic_card_free_chain(struct gelic_card *card,
  *
  * returns 0 on success, <0 on failure
  */
-static int gelic_card_init_chain(struct gelic_card *card,
-                                struct gelic_descr_chain *chain,
-                                struct gelic_descr *start_descr, int no)
+static int __devinit gelic_card_init_chain(struct gelic_card *card,
+                                          struct gelic_descr_chain *chain,
+                                          struct gelic_descr *start_descr,
+                                          int no)
 {
        int i;
        struct gelic_descr *descr;
@@ -407,7 +426,7 @@ rewind:
  *
  * returns 0 on success, < 0 on failure
  */
-static int gelic_card_alloc_rx_skbs(struct gelic_card *card)
+static int __devinit gelic_card_alloc_rx_skbs(struct gelic_card *card)
 {
        struct gelic_descr_chain *chain;
        int ret;
@@ -450,14 +469,14 @@ static void gelic_descr_release_tx(struct gelic_card *card,
 
 static void gelic_card_stop_queues(struct gelic_card *card)
 {
-       netif_stop_queue(card->netdev[GELIC_PORT_ETHERNET]);
+       netif_stop_queue(card->netdev[GELIC_PORT_ETHERNET_0]);
 
        if (card->netdev[GELIC_PORT_WIRELESS])
                netif_stop_queue(card->netdev[GELIC_PORT_WIRELESS]);
 }
 static void gelic_card_wake_queues(struct gelic_card *card)
 {
-       netif_wake_queue(card->netdev[GELIC_PORT_ETHERNET]);
+       netif_wake_queue(card->netdev[GELIC_PORT_ETHERNET_0]);
 
        if (card->netdev[GELIC_PORT_WIRELESS])
                netif_wake_queue(card->netdev[GELIC_PORT_WIRELESS]);
@@ -745,7 +764,7 @@ static inline struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb,
        /* Move the mac addresses to the top of buffer */
        memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN);
 
-       veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
+       veth->h_vlan_proto = cpu_to_be16(ETH_P_8021Q);
        veth->h_vlan_TCI = htons(tag);
 
        return skb;
@@ -998,7 +1017,7 @@ static int gelic_card_decode_one_descr(struct gelic_card *card)
                        goto refill;
                }
        } else
-               netdev = card->netdev[GELIC_PORT_ETHERNET];
+               netdev = card->netdev[GELIC_PORT_ETHERNET_0];
 
        if ((status == GELIC_DESCR_DMA_RESPONSE_ERROR) ||
            (status == GELIC_DESCR_DMA_PROTECTION_ERROR) ||
@@ -1243,14 +1262,58 @@ static int gelic_ether_get_settings(struct net_device *netdev,
        cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg |
                        SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
                        SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
-                       SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
+                       SUPPORTED_1000baseT_Full;
        cmd->advertising = cmd->supported;
-       cmd->autoneg = AUTONEG_ENABLE; /* always enabled */
+       if (card->link_mode & GELIC_LV1_ETHER_AUTO_NEG) {
+               cmd->autoneg = AUTONEG_ENABLE;
+       } else {
+               cmd->autoneg = AUTONEG_DISABLE;
+               cmd->advertising &= ~ADVERTISED_Autoneg;
+       }
        cmd->port = PORT_TP;
 
        return 0;
 }
 
+static int gelic_ether_set_settings(struct net_device *netdev,
+                                   struct ethtool_cmd *cmd)
+{
+       struct gelic_card *card = netdev_card(netdev);
+       u64 mode;
+       int ret;
+
+       if (cmd->autoneg == AUTONEG_ENABLE) {
+               mode = GELIC_LV1_ETHER_AUTO_NEG;
+       } else {
+               switch (cmd->speed) {
+               case SPEED_10:
+                       mode = GELIC_LV1_ETHER_SPEED_10;
+                       break;
+               case SPEED_100:
+                       mode = GELIC_LV1_ETHER_SPEED_100;
+                       break;
+               case SPEED_1000:
+                       mode = GELIC_LV1_ETHER_SPEED_1000;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               if (cmd->duplex == DUPLEX_FULL)
+                       mode |= GELIC_LV1_ETHER_FULL_DUPLEX;
+               else if (cmd->speed == SPEED_1000) {
+                       pr_info("1000 half duplex is not supported.\n");
+                       return -EINVAL;
+               }
+       }
+
+       ret = gelic_card_set_link_mode(card, mode);
+
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 u32 gelic_net_get_rx_csum(struct net_device *netdev)
 {
        struct gelic_card *card = netdev_card(netdev);
@@ -1345,9 +1408,10 @@ done:
        return status;
 }
 
-static struct ethtool_ops gelic_ether_ethtool_ops = {
+static const struct ethtool_ops gelic_ether_ethtool_ops = {
        .get_drvinfo    = gelic_net_get_drvinfo,
        .get_settings   = gelic_ether_get_settings,
+       .set_settings   = gelic_ether_set_settings,
        .get_link       = ethtool_op_get_link,
        .get_tx_csum    = ethtool_op_get_tx_csum,
        .set_tx_csum    = ethtool_op_set_tx_csum,
@@ -1368,7 +1432,7 @@ static void gelic_net_tx_timeout_task(struct work_struct *work)
 {
        struct gelic_card *card =
                container_of(work, struct gelic_card, tx_timeout_task);
-       struct net_device *netdev = card->netdev[GELIC_PORT_ETHERNET];
+       struct net_device *netdev = card->netdev[GELIC_PORT_ETHERNET_0];
 
        dev_info(ctodev(card), "%s:Timed out. Restarting... \n", __func__);
 
@@ -1403,30 +1467,35 @@ void gelic_net_tx_timeout(struct net_device *netdev)
                atomic_dec(&card->tx_timeout_task_counter);
 }
 
+static const struct net_device_ops gelic_netdevice_ops = {
+       .ndo_open = gelic_net_open,
+       .ndo_stop = gelic_net_stop,
+       .ndo_start_xmit = gelic_net_xmit,
+       .ndo_set_multicast_list = gelic_net_set_multi,
+       .ndo_change_mtu = gelic_net_change_mtu,
+       .ndo_tx_timeout = gelic_net_tx_timeout,
+       .ndo_set_mac_address = eth_mac_addr,
+       .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller = gelic_net_poll_controller,
+#endif
+};
+
 /**
  * gelic_ether_setup_netdev_ops - initialization of net_device operations
  * @netdev: net_device structure
  *
  * fills out function pointers in the net_device structure
  */
-static void gelic_ether_setup_netdev_ops(struct net_device *netdev,
-                                        struct napi_struct *napi)
+static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev,
+                                                  struct napi_struct *napi)
 {
-       netdev->open = &gelic_net_open;
-       netdev->stop = &gelic_net_stop;
-       netdev->hard_start_xmit = &gelic_net_xmit;
-       netdev->set_multicast_list = &gelic_net_set_multi;
-       netdev->change_mtu = &gelic_net_change_mtu;
-       /* tx watchdog */
-       netdev->tx_timeout = &gelic_net_tx_timeout;
        netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
        /* NAPI */
        netif_napi_add(netdev, napi,
                       gelic_net_poll, GELIC_NET_NAPI_WEIGHT);
        netdev->ethtool_ops = &gelic_ether_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       netdev->poll_controller = gelic_net_poll_controller;
-#endif
+       netdev->netdev_ops = &gelic_netdevice_ops;
 }
 
 /**
@@ -1439,7 +1508,8 @@ static void gelic_ether_setup_netdev_ops(struct net_device *netdev,
  * gelic_ether_setup_netdev initializes the net_device structure
  * and register it.
  **/
-int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
+int __devinit gelic_net_setup_netdev(struct net_device *netdev,
+                                    struct gelic_card *card)
 {
        int status;
        u64 v1, v2;
@@ -1487,7 +1557,7 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
  * the card and net_device structures are linked to each other
  */
 #define GELIC_ALIGN (32)
-static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev)
+static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **netdev)
 {
        struct gelic_card *card;
        struct gelic_port *port;
@@ -1524,10 +1594,10 @@ static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev)
        /* gelic_port */
        port->netdev = *netdev;
        port->card = card;
-       port->type = GELIC_PORT_ETHERNET;
+       port->type = GELIC_PORT_ETHERNET_0;
 
        /* gelic_card */
-       card->netdev[GELIC_PORT_ETHERNET] = *netdev;
+       card->netdev[GELIC_PORT_ETHERNET_0] = *netdev;
 
        INIT_WORK(&card->tx_timeout_task, gelic_net_tx_timeout_task);
        init_waitqueue_head(&card->waitq);
@@ -1538,7 +1608,7 @@ static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev)
        return card;
 }
 
-static void gelic_card_get_vlan_info(struct gelic_card *card)
+static void __devinit gelic_card_get_vlan_info(struct gelic_card *card)
 {
        u64 v1, v2;
        int status;
@@ -1547,9 +1617,9 @@ static void gelic_card_get_vlan_info(struct gelic_card *card)
                int tx;
                int rx;
        } vlan_id_ix[2] = {
-               [GELIC_PORT_ETHERNET] = {
-                       .tx = GELIC_LV1_VLAN_TX_ETHERNET,
-                       .rx = GELIC_LV1_VLAN_RX_ETHERNET
+               [GELIC_PORT_ETHERNET_0] = {
+                       .tx = GELIC_LV1_VLAN_TX_ETHERNET_0,
+                       .rx = GELIC_LV1_VLAN_RX_ETHERNET_0
                },
                [GELIC_PORT_WIRELESS] = {
                        .tx = GELIC_LV1_VLAN_TX_WIRELESS,
@@ -1594,7 +1664,7 @@ static void gelic_card_get_vlan_info(struct gelic_card *card)
                        i, card->vlan[i].tx, card->vlan[i].rx);
        }
 
-       if (card->vlan[GELIC_PORT_ETHERNET].tx) {
+       if (card->vlan[GELIC_PORT_ETHERNET_0].tx) {
                BUG_ON(!card->vlan[GELIC_PORT_WIRELESS].tx);
                card->vlan_required = 1;
        } else
@@ -1612,7 +1682,7 @@ static void gelic_card_get_vlan_info(struct gelic_card *card)
 /**
  * ps3_gelic_driver_probe - add a device to the control of this driver
  */
-static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
+static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
 {
        struct gelic_card *card;
        struct net_device *netdev;
@@ -1644,12 +1714,14 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
                result = -ENOMEM;
                goto fail_alloc_card;
        }
-       ps3_system_bus_set_driver_data(dev, card);
+       ps3_system_bus_set_drvdata(dev, card);
        card->dev = dev;
 
        /* get internal vlan info */
        gelic_card_get_vlan_info(card);
 
+       card->link_mode = GELIC_LV1_ETHER_AUTO_NEG;
+
        /* setup interrupt */
        result = lv1_net_set_interrupt_status_indicator(bus_id(card),
                                                        dev_id(card),
@@ -1745,7 +1817,7 @@ fail_alloc_irq:
                                               bus_id(card),
                                               0, 0);
 fail_status_indicator:
-       ps3_system_bus_set_driver_data(dev, NULL);
+       ps3_system_bus_set_drvdata(dev, NULL);
        kfree(netdev_card(netdev)->unalign);
        free_netdev(netdev);
 fail_alloc_card:
@@ -1762,10 +1834,13 @@ fail_open:
 
 static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev)
 {
-       struct gelic_card *card = ps3_system_bus_get_driver_data(dev);
+       struct gelic_card *card = ps3_system_bus_get_drvdata(dev);
        struct net_device *netdev0;
        pr_debug("%s: called\n", __func__);
 
+       /* set auto-negotiation */
+       gelic_card_set_link_mode(card, GELIC_LV1_ETHER_AUTO_NEG);
+
 #ifdef CONFIG_GELIC_WIRELESS
        gelic_wl_driver_remove(card);
 #endif
@@ -1783,7 +1858,7 @@ static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev)
        gelic_card_free_chain(card, card->tx_top);
        gelic_card_free_chain(card, card->rx_top);
 
-       netdev0 = card->netdev[GELIC_PORT_ETHERNET];
+       netdev0 = card->netdev[GELIC_PORT_ETHERNET_0];
        /* disconnect event port */
        free_irq(card->irq, card);
        netdev0->irq = NO_IRQ;
@@ -1799,7 +1874,7 @@ static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev)
        kfree(netdev_card(netdev0)->unalign);
        free_netdev(netdev0);
 
-       ps3_system_bus_set_driver_data(dev, NULL);
+       ps3_system_bus_set_drvdata(dev, NULL);
 
        ps3_dma_region_free(dev->d_region);