Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild
[powerpc.git] / drivers / net / cxgb3 / cxgb3_main.c
index dfa035a..67b4b21 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/workqueue.h>
 #include <linux/proc_fs.h>
 #include <linux/rtnetlink.h>
+#include <linux/firmware.h>
 #include <asm/uaccess.h>
 
 #include "common.h"
@@ -74,8 +75,6 @@ enum {
 
 #define EEPROM_MAGIC 0x38E2F10C
 
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
-
 #define CH_DEVICE(devid, ssid, idx) \
        { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx }
 
@@ -186,16 +185,24 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
                        int speed, int duplex, int pause)
 {
        struct net_device *dev = adapter->port[port_id];
+       struct port_info *pi = netdev_priv(dev);
+       struct cmac *mac = &pi->mac;
 
        /* Skip changes from disabled ports. */
        if (!netif_running(dev))
                return;
 
        if (link_stat != netif_carrier_ok(dev)) {
-               if (link_stat)
+               if (link_stat) {
+                       t3_mac_enable(mac, MAC_DIRECTION_RX);
                        netif_carrier_on(dev);
-               else
+               } else {
                        netif_carrier_off(dev);
+                       pi->phy.ops->power_down(&pi->phy, 1);
+                       t3_mac_disable(mac, MAC_DIRECTION_RX);
+                       t3_link_start(&pi->phy, mac, &pi->link_config);
+               }
+
                link_report(dev);
        }
 }
@@ -408,7 +415,7 @@ static void quiesce_rx(struct adapter *adap)
 static int setup_sge_qsets(struct adapter *adap)
 {
        int i, j, err, irq_idx = 0, qset_idx = 0, dummy_dev_idx = 0;
-       unsigned int ntxq = is_offload(adap) ? SGE_TXQ_PER_SET : 1;
+       unsigned int ntxq = SGE_TXQ_PER_SET;
 
        if (adap->params.rev > 0 && !(adap->flags & USING_MSI))
                irq_idx = -1;
@@ -434,27 +441,27 @@ static int setup_sge_qsets(struct adapter *adap)
        return 0;
 }
 
-static ssize_t attr_show(struct class_device *cd, char *buf,
-                        ssize_t(*format) (struct adapter *, char *))
+static ssize_t attr_show(struct device *d, struct device_attribute *attr,
+                        char *buf,
+                        ssize_t(*format) (struct net_device *, char *))
 {
        ssize_t len;
-       struct adapter *adap = to_net_dev(cd)->priv;
 
        /* Synchronize with ioctls that may shut down the device */
        rtnl_lock();
-       len = (*format) (adap, buf);
+       len = (*format) (to_net_dev(d), buf);
        rtnl_unlock();
        return len;
 }
 
-static ssize_t attr_store(struct class_device *cd, const char *buf, size_t len,
-                         ssize_t(*set) (struct adapter *, unsigned int),
+static ssize_t attr_store(struct device *d, struct device_attribute *attr,
+                         const char *buf, size_t len,
+                         ssize_t(*set) (struct net_device *, unsigned int),
                          unsigned int min_val, unsigned int max_val)
 {
        char *endp;
        ssize_t ret;
        unsigned int val;
-       struct adapter *adap = to_net_dev(cd)->priv;
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
@@ -464,7 +471,7 @@ static ssize_t attr_store(struct class_device *cd, const char *buf, size_t len,
                return -EINVAL;
 
        rtnl_lock();
-       ret = (*set) (adap, val);
+       ret = (*set) (to_net_dev(d), val);
        if (!ret)
                ret = len;
        rtnl_unlock();
@@ -472,75 +479,85 @@ static ssize_t attr_store(struct class_device *cd, const char *buf, size_t len,
 }
 
 #define CXGB3_SHOW(name, val_expr) \
-static ssize_t format_##name(struct adapter *adap, char *buf) \
+static ssize_t format_##name(struct net_device *dev, char *buf) \
 { \
+       struct adapter *adap = dev->priv; \
        return sprintf(buf, "%u\n", val_expr); \
 } \
-static ssize_t show_##name(struct class_device *cd, char *buf) \
+static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
+                          char *buf) \
 { \
-       return attr_show(cd, buf, format_##name); \
+       return attr_show(d, attr, buf, format_##name); \
 }
 
-static ssize_t set_nfilters(struct adapter *adap, unsigned int val)
+static ssize_t set_nfilters(struct net_device *dev, unsigned int val)
 {
+       struct adapter *adap = dev->priv;
+       int min_tids = is_offload(adap) ? MC5_MIN_TIDS : 0;
+
        if (adap->flags & FULL_INIT_DONE)
                return -EBUSY;
        if (val && adap->params.rev == 0)
                return -EINVAL;
-       if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers)
+       if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers -
+           min_tids)
                return -EINVAL;
        adap->params.mc5.nfilters = val;
        return 0;
 }
 
-static ssize_t store_nfilters(struct class_device *cd, const char *buf,
-                             size_t len)
+static ssize_t store_nfilters(struct device *d, struct device_attribute *attr,
+                             const char *buf, size_t len)
 {
-       return attr_store(cd, buf, len, set_nfilters, 0, ~0);
+       return attr_store(d, attr, buf, len, set_nfilters, 0, ~0);
 }
 
-static ssize_t set_nservers(struct adapter *adap, unsigned int val)
+static ssize_t set_nservers(struct net_device *dev, unsigned int val)
 {
+       struct adapter *adap = dev->priv;
+
        if (adap->flags & FULL_INIT_DONE)
                return -EBUSY;
-       if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters)
+       if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters -
+           MC5_MIN_TIDS)
                return -EINVAL;
        adap->params.mc5.nservers = val;
        return 0;
 }
 
-static ssize_t store_nservers(struct class_device *cd, const char *buf,
-                             size_t len)
+static ssize_t store_nservers(struct device *d, struct device_attribute *attr,
+                             const char *buf, size_t len)
 {
-       return attr_store(cd, buf, len, set_nservers, 0, ~0);
+       return attr_store(d, attr, buf, len, set_nservers, 0, ~0);
 }
 
 #define CXGB3_ATTR_R(name, val_expr) \
 CXGB3_SHOW(name, val_expr) \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 
 #define CXGB3_ATTR_RW(name, val_expr, store_method) \
 CXGB3_SHOW(name, val_expr) \
-static CLASS_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_method)
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_method)
 
 CXGB3_ATTR_R(cam_size, t3_mc5_size(&adap->mc5));
 CXGB3_ATTR_RW(nfilters, adap->params.mc5.nfilters, store_nfilters);
 CXGB3_ATTR_RW(nservers, adap->params.mc5.nservers, store_nservers);
 
 static struct attribute *cxgb3_attrs[] = {
-       &class_device_attr_cam_size.attr,
-       &class_device_attr_nfilters.attr,
-       &class_device_attr_nservers.attr,
+       &dev_attr_cam_size.attr,
+       &dev_attr_nfilters.attr,
+       &dev_attr_nservers.attr,
        NULL
 };
 
 static struct attribute_group cxgb3_attr_group = {.attrs = cxgb3_attrs };
 
-static ssize_t tm_attr_show(struct class_device *cd, char *buf, int sched)
+static ssize_t tm_attr_show(struct device *d, struct device_attribute *attr,
+                           char *buf, int sched)
 {
        ssize_t len;
        unsigned int v, addr, bpt, cpt;
-       struct adapter *adap = to_net_dev(cd)->priv;
+       struct adapter *adap = to_net_dev(d)->priv;
 
        addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2;
        rtnl_lock();
@@ -560,13 +577,13 @@ static ssize_t tm_attr_show(struct class_device *cd, char *buf, int sched)
        return len;
 }
 
-static ssize_t tm_attr_store(struct class_device *cd, const char *buf,
-                            size_t len, int sched)
+static ssize_t tm_attr_store(struct device *d, struct device_attribute *attr,
+                            const char *buf, size_t len, int sched)
 {
        char *endp;
        ssize_t ret;
        unsigned int val;
-       struct adapter *adap = to_net_dev(cd)->priv;
+       struct adapter *adap = to_net_dev(d)->priv;
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
@@ -584,15 +601,17 @@ static ssize_t tm_attr_store(struct class_device *cd, const char *buf,
 }
 
 #define TM_ATTR(name, sched) \
-static ssize_t show_##name(struct class_device *cd, char *buf) \
+static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
+                          char *buf) \
 { \
-       return tm_attr_show(cd, buf, sched); \
+       return tm_attr_show(d, attr, buf, sched); \
 } \
-static ssize_t store_##name(struct class_device *cd, const char *buf, size_t len) \
+static ssize_t store_##name(struct device *d, struct device_attribute *attr, \
+                           const char *buf, size_t len) \
 { \
-       return tm_attr_store(cd, buf, len, sched); \
+       return tm_attr_store(d, attr, buf, len, sched); \
 } \
-static CLASS_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
 
 TM_ATTR(sched0, 0);
 TM_ATTR(sched1, 1);
@@ -604,14 +623,14 @@ TM_ATTR(sched6, 6);
 TM_ATTR(sched7, 7);
 
 static struct attribute *offload_attrs[] = {
-       &class_device_attr_sched0.attr,
-       &class_device_attr_sched1.attr,
-       &class_device_attr_sched2.attr,
-       &class_device_attr_sched3.attr,
-       &class_device_attr_sched4.attr,
-       &class_device_attr_sched5.attr,
-       &class_device_attr_sched6.attr,
-       &class_device_attr_sched7.attr,
+       &dev_attr_sched0.attr,
+       &dev_attr_sched1.attr,
+       &dev_attr_sched2.attr,
+       &dev_attr_sched3.attr,
+       &dev_attr_sched4.attr,
+       &dev_attr_sched5.attr,
+       &dev_attr_sched6.attr,
+       &dev_attr_sched7.attr,
        NULL
 };
 
@@ -700,6 +719,28 @@ static void bind_qsets(struct adapter *adap)
        }
 }
 
+#define FW_FNAME "t3fw-%d.%d.%d.bin"
+
+static int upgrade_fw(struct adapter *adap)
+{
+       int ret;
+       char buf[64];
+       const struct firmware *fw;
+       struct device *dev = &adap->pdev->dev;
+
+       snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR,
+                FW_VERSION_MINOR, FW_VERSION_MICRO);
+       ret = request_firmware(&fw, buf, dev);
+       if (ret < 0) {
+               dev_err(dev, "could not upgrade firmware: unable to load %s\n",
+                       buf);
+               return ret;
+       }
+       ret = t3_load_fw(adap, fw->data, fw->size);
+       release_firmware(fw);
+       return ret;
+}
+
 /**
  *     cxgb_up - enable the adapter
  *     @adapter: adapter being enabled
@@ -716,6 +757,8 @@ static int cxgb_up(struct adapter *adap)
 
        if (!(adap->flags & FULL_INIT_DONE)) {
                err = t3_check_fw_version(adap);
+               if (err == -EINVAL)
+                       err = upgrade_fw(adap);
                if (err)
                        goto out;
 
@@ -727,6 +770,8 @@ static int cxgb_up(struct adapter *adap)
                if (err)
                        goto out;
 
+               t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
+               
                err = setup_sge_qsets(adap);
                if (err)
                        goto out;
@@ -753,7 +798,8 @@ static int cxgb_up(struct adapter *adap)
                                      t3_intr_handler(adap,
                                                      adap->sge.qs[0].rspq.
                                                      polling),
-                                     (adap->flags & USING_MSI) ? 0 : SA_SHIRQ,
+                                     (adap->flags & USING_MSI) ?
+                                      0 : IRQF_SHARED,
                                      adap->name, adap)))
                goto irq_err;
 
@@ -836,7 +882,7 @@ static int offload_open(struct net_device *dev)
        init_smt(adapter);
 
        /* Never mind if the next step fails */
-       sysfs_create_group(&tdev->lldev->class_dev.kobj, &offload_attr_group);
+       sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group);
 
        /* Call back all registered clients */
        cxgb3_add_clients(tdev);
@@ -861,7 +907,7 @@ static int offload_close(struct t3cdev *tdev)
        /* Call back all registered clients */
        cxgb3_remove_clients(tdev);
 
-       sysfs_remove_group(&tdev->lldev->class_dev.kobj, &offload_attr_group);
+       sysfs_remove_group(&tdev->lldev->dev.kobj, &offload_attr_group);
 
        tdev->lldev = NULL;
        cxgb3_set_dummy_ops(tdev);
@@ -886,7 +932,7 @@ static int cxgb_open(struct net_device *dev)
                return err;
 
        set_bit(pi->port_id, &adapter->open_device_map);
-       if (!ofld_disable) {
+       if (is_offload(adapter) && !ofld_disable) {
                err = offload_open(dev);
                if (err)
                        printk(KERN_WARNING
@@ -1023,7 +1069,11 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
        "VLANinsertions     ",
        "TxCsumOffload      ",
        "RxCsumGood         ",
-       "RxDrops            "
+       "RxDrops            ",
+
+       "CheckTXEnToggled   ",
+       "CheckResets        ",
+
 };
 
 static int get_stats_count(struct net_device *dev)
@@ -1137,6 +1187,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
        *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM);
        *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD);
        *data++ = s->rx_cong_drops;
+
+       *data++ = s->num_toggled;
+       *data++ = s->num_resets;
 }
 
 static inline void reg_block_dump(struct adapter *ap, void *buf,
@@ -1354,23 +1407,27 @@ static int set_rx_csum(struct net_device *dev, u32 data)
 
 static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
 {
-       struct adapter *adapter = dev->priv;
+       const struct adapter *adapter = dev->priv;
+       const struct port_info *pi = netdev_priv(dev);
+       const struct qset_params *q = &adapter->params.sge.qset[pi->first_qset];
 
        e->rx_max_pending = MAX_RX_BUFFERS;
        e->rx_mini_max_pending = 0;
        e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
        e->tx_max_pending = MAX_TXQ_ENTRIES;
 
-       e->rx_pending = adapter->params.sge.qset[0].fl_size;
-       e->rx_mini_pending = adapter->params.sge.qset[0].rspq_size;
-       e->rx_jumbo_pending = adapter->params.sge.qset[0].jumbo_size;
-       e->tx_pending = adapter->params.sge.qset[0].txq_size[0];
+       e->rx_pending = q->fl_size;
+       e->rx_mini_pending = q->rspq_size;
+       e->rx_jumbo_pending = q->jumbo_size;
+       e->tx_pending = q->txq_size[0];
 }
 
 static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
 {
        int i;
+       struct qset_params *q;
        struct adapter *adapter = dev->priv;
+       const struct port_info *pi = netdev_priv(dev);
 
        if (e->rx_pending > MAX_RX_BUFFERS ||
            e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
@@ -1385,9 +1442,8 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
        if (adapter->flags & FULL_INIT_DONE)
                return -EBUSY;
 
-       for (i = 0; i < SGE_QSETS; ++i) {
-               struct qset_params *q = &adapter->params.sge.qset[i];
-
+       q = &adapter->params.sge.qset[pi->first_qset];
+       for (i = 0; i < pi->nqsets; ++i, ++q) {
                q->rspq_size = e->rx_mini_pending;
                q->fl_size = e->rx_pending;
                q->jumbo_size = e->rx_jumbo_pending;
@@ -1544,32 +1600,6 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
                return -EFAULT;
 
        switch (cmd) {
-       case CHELSIO_SETREG:{
-               struct ch_reg edata;
-
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
-               if (copy_from_user(&edata, useraddr, sizeof(edata)))
-                       return -EFAULT;
-               if ((edata.addr & 3) != 0
-                       || edata.addr >= adapter->mmio_len)
-                       return -EINVAL;
-               writel(edata.val, adapter->regs + edata.addr);
-               break;
-       }
-       case CHELSIO_GETREG:{
-               struct ch_reg edata;
-
-               if (copy_from_user(&edata, useraddr, sizeof(edata)))
-                       return -EFAULT;
-               if ((edata.addr & 3) != 0
-                       || edata.addr >= adapter->mmio_len)
-                       return -EINVAL;
-               edata.val = readl(adapter->regs + edata.addr);
-               if (copy_to_user(useraddr, &edata, sizeof(edata)))
-                       return -EFAULT;
-               break;
-       }
        case CHELSIO_SET_QSET_PARAMS:{
                int i;
                struct qset_params *q;
@@ -1833,10 +1863,10 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
                        return -EINVAL;
 
                /*
-                       * Version scheme:
-                       * bits 0..9: chip version
-                       * bits 10..15: chip revision
-                       */
+                * Version scheme:
+                * bits 0..9: chip version
+                * bits 10..15: chip revision
+                */
                t.version = 3 | (adapter->params.rev << 10);
                if (copy_to_user(useraddr, &t, sizeof(t)))
                        return -EFAULT;
@@ -1885,20 +1915,6 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
                                                t.trace_rx);
                break;
        }
-       case CHELSIO_SET_PKTSCHED:{
-               struct ch_pktsched_params p;
-
-               if (!capable(CAP_NET_ADMIN))
-                               return -EPERM;
-               if (!adapter->open_device_map)
-                               return -EAGAIN; /* uP and SGE must be running */
-               if (copy_from_user(&p, useraddr, sizeof(p)))
-                               return -EFAULT;
-               send_pktsched_cmd(adapter, p.sched, p.idx, p.min, p.max,
-                                 p.binding);
-               break;
-                       
-       }
        default:
                return -EOPNOTSUPP;
        }
@@ -2099,6 +2115,42 @@ static void check_link_status(struct adapter *adapter)
        }
 }
 
+static void check_t3b2_mac(struct adapter *adapter)
+{
+       int i;
+
+       if (!rtnl_trylock())    /* synchronize with ifdown */
+               return;
+
+       for_each_port(adapter, i) {
+               struct net_device *dev = adapter->port[i];
+               struct port_info *p = netdev_priv(dev);
+               int status;
+
+               if (!netif_running(dev))
+                       continue;
+
+               status = 0;
+               if (netif_running(dev) && netif_carrier_ok(dev))
+                       status = t3b2_mac_watchdog_task(&p->mac);
+               if (status == 1)
+                       p->mac.stats.num_toggled++;
+               else if (status == 2) {
+                       struct cmac *mac = &p->mac;
+
+                       t3_mac_set_mtu(mac, dev->mtu);
+                       t3_mac_set_address(mac, 0, dev->dev_addr);
+                       cxgb_set_rxmode(dev);
+                       t3_link_start(&p->phy, mac, &p->link_config);
+                       t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
+                       t3_port_intr_enable(adapter, p->port_id);
+                       p->mac.stats.num_resets++;
+               }
+       }
+       rtnl_unlock();
+}
+
+
 static void t3_adap_check_task(struct work_struct *work)
 {
        struct adapter *adapter = container_of(work, struct adapter,
@@ -2119,6 +2171,9 @@ static void t3_adap_check_task(struct work_struct *work)
                adapter->check_task_cnt = 0;
        }
 
+       if (p->rev == T3_REV_B2)
+               check_t3b2_mac(adapter);
+
        /* Schedule the next check update if any port is active. */
        spin_lock(&adapter->work_lock);
        if (adapter->open_device_map & PORT_MASK)
@@ -2227,9 +2282,9 @@ static void __devinit print_port_info(struct adapter *adap,
 
                if (!test_bit(i, &adap->registered_device_map))
                        continue;
-               printk(KERN_INFO "%s: %s %s RNIC (rev %d) %s%s\n",
+               printk(KERN_INFO "%s: %s %s %sNIC (rev %d) %s%s\n",
                       dev->name, ai->desc, pi->port_type->desc,
-                      adap->params.rev, buf,
+                      is_offload(adap) ? "R" : "", adap->params.rev, buf,
                       (adap->flags & USING_MSIX) ? " MSI-X" :
                       (adap->flags & USING_MSI) ? " MSI" : "");
                if (adap->name == dev->name && adap->params.vpd.mclk)
@@ -2420,7 +2475,7 @@ static int __devinit init_one(struct pci_dev *pdev,
        else if (msi > 0 && pci_enable_msi(pdev) == 0)
                adapter->flags |= USING_MSI;
 
-       err = sysfs_create_group(&adapter->port[0]->class_dev.kobj,
+       err = sysfs_create_group(&adapter->port[0]->dev.kobj,
                                 &cxgb3_attr_group);
 
        print_port_info(adapter, ai);
@@ -2452,7 +2507,7 @@ static void __devexit remove_one(struct pci_dev *pdev)
                struct adapter *adapter = dev->priv;
 
                t3_sge_stop(adapter);
-               sysfs_remove_group(&adapter->port[0]->class_dev.kobj,
+               sysfs_remove_group(&adapter->port[0]->dev.kobj,
                                   &cxgb3_attr_group);
 
                for_each_port(adapter, i)