]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/cxgb3/cxgb3_main.c
Merge branch 'for-2.6.21' of master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
[linux-2.6-omap-h63xx.git] / drivers / net / cxgb3 / cxgb3_main.c
index 54c49acd86b4a001345d3e66d1df0555b1a93a14..26240fd5e76835d4fa3af47b44df76675d50fb68 100644 (file)
@@ -1,14 +1,34 @@
 /*
- * This file is part of the Chelsio T3 Ethernet driver for Linux.
+ * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
  *
- * Copyright (C) 2003-2006 Chelsio Communications.  All rights reserved.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
- * release for licensing terms and conditions.
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
  */
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -22,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"
@@ -54,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 }
 
@@ -75,7 +94,7 @@ static const struct pci_device_id cxgb3_pci_tbl[] = {
 
 MODULE_DESCRIPTION(DRV_DESC);
 MODULE_AUTHOR("Chelsio Communications");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, cxgb3_pci_tbl);
 
@@ -166,16 +185,26 @@ 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_set_reg_field(adapter,
+                                        A_XGM_TXFIFO_CFG + mac->offset,
+                                        F_ENDROPPKT, 0);
                        netif_carrier_on(dev);
-               else
+               } else {
                        netif_carrier_off(dev);
+                       t3_set_reg_field(adapter,
+                                        A_XGM_TXFIFO_CFG + mac->offset,
+                                        F_ENDROPPKT, F_ENDROPPKT);
+               }
+
                link_report(dev);
        }
 }
@@ -388,7 +417,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;
@@ -414,27 +443,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;
@@ -444,7 +473,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();
@@ -452,75 +481,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();
@@ -540,13 +579,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;
@@ -564,15 +603,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);
@@ -584,14 +625,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
 };
 
@@ -649,6 +690,59 @@ static void init_port_mtus(struct adapter *adapter)
        t3_write_reg(adapter, A_TP_MTU_PORT_TABLE, mtus);
 }
 
+static void send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo,
+                             int hi, int port)
+{
+       struct sk_buff *skb;
+       struct mngt_pktsched_wr *req;
+
+       skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
+       req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req));
+       req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT));
+       req->mngt_opcode = FW_MNGTOPCODE_PKTSCHED_SET;
+       req->sched = sched;
+       req->idx = qidx;
+       req->min = lo;
+       req->max = hi;
+       req->binding = port;
+       t3_mgmt_tx(adap, skb);
+}
+
+static void bind_qsets(struct adapter *adap)
+{
+       int i, j;
+
+       for_each_port(adap, i) {
+               const struct port_info *pi = adap2pinfo(adap, i);
+
+               for (j = 0; j < pi->nqsets; ++j)
+                       send_pktsched_cmd(adap, 1, pi->first_qset + j, -1,
+                                         -1, i);
+       }
+}
+
+#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
@@ -665,11 +759,10 @@ static int cxgb_up(struct adapter *adap)
 
        if (!(adap->flags & FULL_INIT_DONE)) {
                err = t3_check_fw_version(adap);
-               if (err) {
-                       dev_err(&adap->pdev->dev,
-                               "adapter FW is not compatible with driver\n");
+               if (err == -EINVAL)
+                       err = upgrade_fw(adap);
+               if (err)
                        goto out;
-               }
 
                err = init_dummy_netdevs(adap);
                if (err)
@@ -705,12 +798,18 @@ 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;
 
        t3_sge_start(adap);
        t3_intr_enable(adap);
+
+       if ((adap->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX)
+               bind_qsets(adap);
+       adap->flags |= QUEUES_BOUND;
+
 out:
        return err;
 irq_err:
@@ -783,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);
@@ -808,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);
@@ -833,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
@@ -970,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)
@@ -1002,10 +1105,14 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
        strcpy(info->bus_info, pci_name(adapter->pdev));
        if (!fw_vers)
                strcpy(info->fw_version, "N/A");
-       else
+       else {
                snprintf(info->fw_version, sizeof(info->fw_version),
-                        "%s %u.%u", (fw_vers >> 24) ? "T" : "N",
-                        (fw_vers >> 12) & 0xfff, fw_vers & 0xfff);
+                        "%s %u.%u.%u",
+                        G_FW_VERSION_TYPE(fw_vers) ? "T" : "N",
+                        G_FW_VERSION_MAJOR(fw_vers),
+                        G_FW_VERSION_MINOR(fw_vers),
+                        G_FW_VERSION_MICRO(fw_vers));
+       }
 }
 
 static void get_strings(struct net_device *dev, u32 stringset, u8 * data)
@@ -1080,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,
@@ -1297,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 ||
@@ -1328,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;
@@ -1487,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;
@@ -1776,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;
@@ -1828,36 +1915,6 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
                                                t.trace_rx);
                break;
        }
-       case CHELSIO_SET_PKTSCHED:{
-               struct sk_buff *skb;
-               struct ch_pktsched_params p;
-               struct mngt_pktsched_wr *req;
-
-               if (!(adapter->flags & FULL_INIT_DONE))
-                       return -EIO;    /* uP must be up and running */
-               if (copy_from_user(&p, useraddr, sizeof(p)))
-                       return -EFAULT;
-               skb = alloc_skb(sizeof(*req), GFP_KERNEL);
-               if (!skb)
-                       return -ENOMEM;
-               req =
-                       (struct mngt_pktsched_wr *)skb_put(skb,
-                                                       sizeof(*req));
-               req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT));
-               req->mngt_opcode = FW_MNGTOPCODE_PKTSCHED_SET;
-               req->sched = p.sched;
-               req->idx = p.idx;
-               req->min = p.min;
-               req->max = p.max;
-               req->binding = p.binding;
-               printk(KERN_INFO
-                       "pktsched: sched %u idx %u min %u max %u binding %u\n",
-                       req->sched, req->idx, req->min, req->max,
-                       req->binding);
-               skb->priority = 1;
-               offload_tx(&adapter->tdev, skb);
-               break;
-       }
        default:
                return -EOPNOTSUPP;
        }
@@ -2058,6 +2115,40 @@ static void check_link_status(struct adapter *adapter)
        }
 }
 
+static void check_t3b2_mac(struct adapter *adapter)
+{
+       int i;
+
+       rtnl_lock();                      /* synchronize with ifdown */
+       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,
@@ -2078,6 +2169,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)
@@ -2186,9 +2280,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)
@@ -2379,7 +2473,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);
@@ -2411,7 +2505,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)