Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Mar 2010 15:33:17 +0000 (07:33 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Mar 2010 15:33:17 +0000 (07:33 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (48 commits)
  IB/srp: Clean up error path in srp_create_target_ib()
  IB/srp: Split send and recieve CQs to reduce number of interrupts
  RDMA/nes: Add support for KR device id 0x0110
  IB/uverbs: Use anon_inodes instead of private infinibandeventfs
  IB/core: Fix and clean up ib_ud_header_init()
  RDMA/cxgb3: Mark RDMA device with CXIO_ERROR_FATAL when removing
  RDMA/cxgb3: Don't allocate the SW queue for user mode CQs
  RDMA/cxgb3: Increase the max CQ depth
  RDMA/cxgb3: Doorbell overflow avoidance and recovery
  IB/core: Pack struct ib_device a little tighter
  IB/ucm: Clean whitespace errors
  IB/ucm: Increase maximum devices supported
  IB/ucm: Use stack variable 'base' in ib_ucm_add_one
  IB/ucm: Use stack variable 'devnum' in ib_ucm_add_one
  IB/umad: Clean whitespace
  IB/umad: Increase maximum devices supported
  IB/umad: Use stack variable 'base' in ib_umad_init_port
  IB/umad: Use stack variable 'devnum' in ib_umad_init_port
  IB/umad: Remove port_table[]
  IB/umad: Convert *cdev to cdev in struct ib_umad_port
  ...

1  2 
drivers/infiniband/hw/nes/nes_nic.c
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/sge.c
drivers/net/cxgb3/t3_hw.c

index 9384f5d3d33b49ce049eea5ac389598d511a0e0f,7dd6ce6e7b991ddb650a8c092de1031aa080b5a4..a1d79b6856ac59c1961b1cb3f58267ce2a7da2a6
@@@ -810,20 -810,6 +810,20 @@@ static int nes_netdev_set_mac_address(s
  }
  
  
 +static void set_allmulti(struct nes_device *nesdev, u32 nic_active_bit)
 +{
 +      u32 nic_active;
 +
 +      nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
 +      nic_active |= nic_active_bit;
 +      nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
 +      nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
 +      nic_active &= ~nic_active_bit;
 +      nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
 +}
 +
 +#define get_addr(addrs, index) ((addrs) + (index) * ETH_ALEN)
 +
  /**
   * nes_netdev_set_multicast_list
   */
@@@ -832,6 -818,7 +832,6 @@@ static void nes_netdev_set_multicast_li
        struct nes_vnic *nesvnic = netdev_priv(netdev);
        struct nes_device *nesdev = nesvnic->nesdev;
        struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
 -      struct dev_mc_list *multicast_addr;
        u32 nic_active_bit;
        u32 nic_active;
        u32 perfect_filter_register_address;
                                        nics_per_function, 4);
        u8 max_pft_entries_avaiable = NES_PFT_SIZE - pft_entries_preallocated;
        unsigned long flags;
 +      int mc_count = netdev_mc_count(netdev);
  
        spin_lock_irqsave(&nesadapter->resource_lock, flags);
        nic_active_bit = 1 << nesvnic->nic_index;
                mc_all_on = 1;
        } else if ((netdev->flags & IFF_ALLMULTI) ||
                           (nesvnic->nic_index > 3)) {
 -              nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
 -              nic_active |= nic_active_bit;
 -              nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
 -              nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
 -              nic_active &= ~nic_active_bit;
 -              nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
 +              set_allmulti(nesdev, nic_active_bit);
                mc_all_on = 1;
        } else {
                nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
        }
  
        nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n",
 -                netdev->mc_count, !!(netdev->flags & IFF_PROMISC),
 +                mc_count, !!(netdev->flags & IFF_PROMISC),
                  !!(netdev->flags & IFF_ALLMULTI));
        if (!mc_all_on) {
 -              multicast_addr = netdev->mc_list;
 +              char *addrs;
 +              int i;
 +              struct dev_mc_list *mcaddr;
 +
 +              addrs = kmalloc(ETH_ALEN * mc_count, GFP_ATOMIC);
 +              if (!addrs) {
 +                      set_allmulti(nesdev, nic_active_bit);
 +                      goto unlock;
 +              }
 +              i = 0;
 +              netdev_for_each_mc_addr(mcaddr, netdev)
 +                      memcpy(get_addr(addrs, i++),
 +                             mcaddr->dmi_addr, ETH_ALEN);
 +
                perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW +
                                                pft_entries_preallocated * 0x8;
 -              for (mc_index = 0; mc_index < max_pft_entries_avaiable;
 -              mc_index++) {
 -                      while (multicast_addr && nesvnic->mcrq_mcast_filter &&
 +              for (i = 0, mc_index = 0; mc_index < max_pft_entries_avaiable;
 +                   mc_index++) {
 +                      while (i < mc_count && nesvnic->mcrq_mcast_filter &&
                        ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic,
 -                                      multicast_addr->dmi_addr)) == 0)) {
 -                              multicast_addr = multicast_addr->next;
 -                      }
 +                                      get_addr(addrs, i++))) == 0));
                        if (mc_nic_index < 0)
                                mc_nic_index = nesvnic->nic_index;
                        while (nesadapter->pft_mcast_map[mc_index] < 16 &&
                        }
                        if (mc_index >= max_pft_entries_avaiable)
                                break;
 -                      if (multicast_addr) {
 +                      if (i < mc_count) {
 +                              char *addr = get_addr(addrs, i++);
 +
                                nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %pM to register 0x%04X nic_idx=%d\n",
 -                                        multicast_addr->dmi_addr,
 +                                        addr,
                                          perfect_filter_register_address+(mc_index * 8),
                                          mc_nic_index);
 -                              macaddr_high  = ((u16)multicast_addr->dmi_addr[0]) << 8;
 -                              macaddr_high += (u16)multicast_addr->dmi_addr[1];
 -                              macaddr_low   = ((u32)multicast_addr->dmi_addr[2]) << 24;
 -                              macaddr_low  += ((u32)multicast_addr->dmi_addr[3]) << 16;
 -                              macaddr_low  += ((u32)multicast_addr->dmi_addr[4]) << 8;
 -                              macaddr_low  += (u32)multicast_addr->dmi_addr[5];
 +                              macaddr_high  = ((u16) addr[0]) << 8;
 +                              macaddr_high += (u16) addr[1];
 +                              macaddr_low   = ((u32) addr[2]) << 24;
 +                              macaddr_low  += ((u32) addr[3]) << 16;
 +                              macaddr_low  += ((u32) addr[4]) << 8;
 +                              macaddr_low  += (u32) addr[5];
                                nes_write_indexed(nesdev,
                                                perfect_filter_register_address+(mc_index * 8),
                                                macaddr_low);
                                                perfect_filter_register_address+4+(mc_index * 8),
                                                (u32)macaddr_high | NES_MAC_ADDR_VALID |
                                                ((((u32)(1<<mc_nic_index)) << 16)));
 -                              multicast_addr = multicast_addr->next;
                                nesadapter->pft_mcast_map[mc_index] =
                                                        nesvnic->nic_index;
                        } else {
                                nesadapter->pft_mcast_map[mc_index] = 255;
                        }
                }
 +              kfree(addrs);
                /* PFT is not large enough */
 -              if (multicast_addr && multicast_addr->next) {
 -                      nic_active = nes_read_indexed(nesdev,
 -                                              NES_IDX_NIC_MULTICAST_ALL);
 -                      nic_active |= nic_active_bit;
 -                      nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL,
 -                                                              nic_active);
 -                      nic_active = nes_read_indexed(nesdev,
 -                                              NES_IDX_NIC_UNICAST_ALL);
 -                      nic_active &= ~nic_active_bit;
 -                      nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL,
 -                                                              nic_active);
 -              }
 +              if (i < mc_count)
 +                      set_allmulti(nesdev, nic_active_bit);
        }
  
 +unlock:
        spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
  }
  
@@@ -1243,8 -1230,8 +1243,8 @@@ static void nes_netdev_get_ethtool_stat
        target_stat_values[++index] = cm_packets_received;
        target_stat_values[++index] = cm_packets_dropped;
        target_stat_values[++index] = cm_packets_retrans;
-       target_stat_values[++index] = cm_listens_created;
-       target_stat_values[++index] = cm_listens_destroyed;
+       target_stat_values[++index] = atomic_read(&cm_listens_created);
+       target_stat_values[++index] = atomic_read(&cm_listens_destroyed);
        target_stat_values[++index] = cm_backlog_drops;
        target_stat_values[++index] = atomic_read(&cm_loopbacks);
        target_stat_values[++index] = atomic_read(&cm_nodes_created);
@@@ -1474,9 -1461,9 +1474,9 @@@ static int nes_netdev_get_settings(stru
                }
                return 0;
        }
-       if ((phy_type == NES_PHY_TYPE_IRIS) ||
-           (phy_type == NES_PHY_TYPE_ARGUS) ||
-           (phy_type == NES_PHY_TYPE_SFP_D)) {
+       if ((phy_type == NES_PHY_TYPE_ARGUS) ||
+           (phy_type == NES_PHY_TYPE_SFP_D) ||
+           (phy_type == NES_PHY_TYPE_KR)) {
                et_cmd->transceiver = XCVR_EXTERNAL;
                et_cmd->port        = PORT_FIBRE;
                et_cmd->supported   = SUPPORTED_FIBRE;
@@@ -1596,8 -1583,7 +1596,7 @@@ struct net_device *nes_netdev_init(stru
        struct net_device *netdev;
        struct nic_qp_map *curr_qp_map;
        u32 u32temp;
-       u16 phy_data;
-       u16 temp_phy_data;
+       u8 phy_type = nesdev->nesadapter->phy_type[nesdev->mac_index];
  
        netdev = alloc_etherdev(sizeof(struct nes_vnic));
        if (!netdev) {
  
        if ((nesdev->netdev_count == 0) &&
            ((PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index) ||
-            ((nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) &&
+            ((phy_type == NES_PHY_TYPE_PUMA_1G) &&
              (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) ||
               ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) {
-               /*
-                * nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
-                *              NES_IDX_PHY_PCS_CONTROL_STATUS0 + (0x200 * (nesvnic->logical_port & 1)));
-                */
                u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
                                (0x200 * (nesdev->mac_index & 1)));
-               if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_PUMA_1G) {
+               if (phy_type != NES_PHY_TYPE_PUMA_1G) {
                        u32temp |= 0x00200000;
                        nes_write_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
                                (0x200 * (nesdev->mac_index & 1)), u32temp);
                }
  
-               u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
-                               (0x200 * (nesdev->mac_index & 1)));
-               if ((u32temp&0x0f1f0000) == 0x0f0f0000) {
-                       if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_IRIS) {
-                               nes_init_phy(nesdev);
-                               nes_read_10G_phy_reg(nesdev, nesdev->nesadapter->phy_index[nesdev->mac_index], 1, 1);
-                               temp_phy_data = (u16)nes_read_indexed(nesdev,
-                                                                       NES_IDX_MAC_MDIO_CONTROL);
-                               u32temp = 20;
-                               do {
-                                       nes_read_10G_phy_reg(nesdev, nesdev->nesadapter->phy_index[nesdev->mac_index], 1, 1);
-                                       phy_data = (u16)nes_read_indexed(nesdev,
-                                                                       NES_IDX_MAC_MDIO_CONTROL);
-                                       if ((phy_data == temp_phy_data) || (!(--u32temp)))
-                                               break;
-                                       temp_phy_data = phy_data;
-                               } while (1);
-                               if (phy_data & 4) {
-                                       nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
-                                       nesvnic->linkup = 1;
-                               } else {
-                                       nes_debug(NES_DBG_INIT, "The Link is DOWN!!.\n");
-                               }
-                       } else {
-                               nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
-                               nesvnic->linkup = 1;
-                       }
-               } else if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) {
-                       nes_debug(NES_DBG_INIT, "mac_index=%d, logical_port=%d, u32temp=0x%04X, PCI_FUNC=%d\n",
-                               nesdev->mac_index, nesvnic->logical_port, u32temp, PCI_FUNC(nesdev->pcidev->devfn));
-                       if (((nesdev->mac_index < 2) && ((u32temp&0x01010000) == 0x01010000)) ||
-                           ((nesdev->mac_index > 1) && ((u32temp&0x02020000) == 0x02020000)))  {
-                               nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
-                               nesvnic->linkup = 1;
-                       }
-               }
                /* clear the MAC interrupt status, assumes direct logical to physical mapping */
                u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));
                nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp);
                nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp);
  
-               if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_IRIS)
-                       nes_init_phy(nesdev);
+               nes_init_phy(nesdev);
  
        }
  
index 6fd968abb073109449ef52d9a8895ed12709aa83,37945fce7fa50d9c4b2a3b7c2beeae8f9ca396fb..3e453e1d97e72ff4b07d040fb7793ae57737d387
@@@ -45,6 -45,7 +45,7 @@@
  #include <linux/firmware.h>
  #include <linux/log2.h>
  #include <linux/stringify.h>
+ #include <linux/sched.h>
  #include <asm/uaccess.h>
  
  #include "common.h"
@@@ -80,7 -81,7 +81,7 @@@ enum 
  #define CH_DEVICE(devid, idx) \
        { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx }
  
 -static const struct pci_device_id cxgb3_pci_tbl[] = {
 +static DEFINE_PCI_DEVICE_TABLE(cxgb3_pci_tbl) = {
        CH_DEVICE(0x20, 0),     /* PE9000 */
        CH_DEVICE(0x21, 1),     /* T302E */
        CH_DEVICE(0x22, 2),     /* T310E */
@@@ -140,7 -141,7 +141,7 @@@ MODULE_PARM_DESC(ofld_disable, "whethe
   * will block keventd as it needs the rtnl lock, and we'll deadlock waiting
   * for our work to complete.  Get our own work queue to solve this.
   */
- static struct workqueue_struct *cxgb3_wq;
+ struct workqueue_struct *cxgb3_wq;
  
  /**
   *    link_report - show link status and link speed/duplex
@@@ -324,9 -325,11 +325,9 @@@ void t3_os_phymod_changed(struct adapte
  
  static void cxgb_set_rxmode(struct net_device *dev)
  {
 -      struct t3_rx_mode rm;
        struct port_info *pi = netdev_priv(dev);
  
 -      init_rx_mode(&rm, dev, dev->mc_list);
 -      t3_mac_set_rx_mode(&pi->mac, &rm);
 +      t3_mac_set_rx_mode(&pi->mac, dev);
  }
  
  /**
   */
  static void link_start(struct net_device *dev)
  {
 -      struct t3_rx_mode rm;
        struct port_info *pi = netdev_priv(dev);
        struct cmac *mac = &pi->mac;
  
 -      init_rx_mode(&rm, dev, dev->mc_list);
        t3_mac_reset(mac);
        t3_mac_set_num_ucast(mac, MAX_MAC_IDX);
        t3_mac_set_mtu(mac, dev->mtu);
        t3_mac_set_address(mac, LAN_MAC_IDX, dev->dev_addr);
        t3_mac_set_address(mac, SAN_MAC_IDX, pi->iscsic.mac_addr);
 -      t3_mac_set_rx_mode(mac, &rm);
 +      t3_mac_set_rx_mode(mac, dev);
        t3_link_start(&pi->phy, mac, &pi->link_config);
        t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
  }
@@@ -586,6 -591,19 +587,19 @@@ static void setup_rss(struct adapter *a
                      V_RRCPLCPUSIZE(6) | F_HASHTOEPLITZ, cpus, rspq_map);
  }
  
+ static void ring_dbs(struct adapter *adap)
+ {
+       int i, j;
+       for (i = 0; i < SGE_QSETS; i++) {
+               struct sge_qset *qs = &adap->sge.qs[i];
+               if (qs->adap)
+                       for (j = 0; j < SGE_TXQ_PER_SET; j++)
+                               t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX | V_EGRCNTX(qs->txq[j].cntxt_id));
+       }
+ }
  static void init_napi(struct adapter *adap)
  {
        int i;
@@@ -2750,6 -2768,42 +2764,42 @@@ static void t3_adap_check_task(struct w
        spin_unlock_irq(&adapter->work_lock);
  }
  
+ static void db_full_task(struct work_struct *work)
+ {
+       struct adapter *adapter = container_of(work, struct adapter,
+                                              db_full_task);
+       cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_FULL, 0);
+ }
+ static void db_empty_task(struct work_struct *work)
+ {
+       struct adapter *adapter = container_of(work, struct adapter,
+                                              db_empty_task);
+       cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_EMPTY, 0);
+ }
+ static void db_drop_task(struct work_struct *work)
+ {
+       struct adapter *adapter = container_of(work, struct adapter,
+                                              db_drop_task);
+       unsigned long delay = 1000;
+       unsigned short r;
+       cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_DROP, 0);
+       /*
+        * Sleep a while before ringing the driver qset dbs.
+        * The delay is between 1000-2023 usecs.
+        */
+       get_random_bytes(&r, 2);
+       delay += r & 1023;
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout(usecs_to_jiffies(delay));
+       ring_dbs(adapter);
+ }
  /*
   * Processes external (PHY) interrupts in process context.
   */
@@@ -3218,6 -3272,11 +3268,11 @@@ static int __devinit init_one(struct pc
        INIT_LIST_HEAD(&adapter->adapter_list);
        INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task);
        INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task);
+       INIT_WORK(&adapter->db_full_task, db_full_task);
+       INIT_WORK(&adapter->db_empty_task, db_empty_task);
+       INIT_WORK(&adapter->db_drop_task, db_drop_task);
        INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task);
  
        for (i = 0; i < ai->nports0 + ai->nports1; ++i) {
diff --combined drivers/net/cxgb3/sge.c
index 048205903741c104f3e3f364fbb2b06b19c64850,9b434461c4f1b615f840c349e114b22fe6854042..78e265b484b64c20baf6d3ab951b3db176415d76
@@@ -42,6 -42,7 +42,7 @@@
  #include "sge_defs.h"
  #include "t3_cpl.h"
  #include "firmware_exports.h"
+ #include "cxgb3_offload.h"
  
  #define USE_GTS 0
  
@@@ -480,7 -481,6 +481,7 @@@ static inline void ring_fl_db(struct ad
  {
        if (q->pend_cred >= q->credits / 4) {
                q->pend_cred = 0;
 +              wmb();
                t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id));
        }
  }
@@@ -2287,14 -2287,11 +2288,14 @@@ static int process_responses(struct ada
        while (likely(budget_left && is_new_response(r, q))) {
                int packet_complete, eth, ethpad = 2, lro = qs->lro_enabled;
                struct sk_buff *skb = NULL;
 -              u32 len, flags = ntohl(r->flags);
 -              __be32 rss_hi = *(const __be32 *)r,
 -                     rss_lo = r->rss_hdr.rss_hash_val;
 +              u32 len, flags;
 +              __be32 rss_hi, rss_lo;
  
 +              rmb();
                eth = r->rss_hdr.opcode == CPL_RX_PKT;
 +              rss_hi = *(const __be32 *)r;
 +              rss_lo = r->rss_hdr.rss_hash_val;
 +              flags = ntohl(r->flags);
  
                if (unlikely(flags & F_RSPD_ASYNC_NOTIF)) {
                        skb = alloc_skb(AN_PKT_SIZE, GFP_ATOMIC);
@@@ -2505,10 -2502,7 +2506,10 @@@ static int process_pure_responses(struc
                        refill_rspq(adap, q, q->credits);
                        q->credits = 0;
                }
 -      } while (is_new_response(r, q) && is_pure_response(r));
 +              if (!is_new_response(r, q))
 +                      break;
 +              rmb();
 +      } while (is_pure_response(r));
  
        if (sleeping)
                check_ring_db(adap, qs, sleeping);
@@@ -2542,7 -2536,6 +2543,7 @@@ static inline int handle_responses(stru
  
        if (!is_new_response(r, q))
                return -1;
 +      rmb();
        if (is_pure_response(r) && process_pure_responses(adap, qs, r) == 0) {
                t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) |
                             V_NEWTIMER(q->holdoff_tmr) | V_NEWINDEX(q->cidx));
@@@ -2841,8 -2834,13 +2842,13 @@@ void t3_sge_err_intr_handler(struct ada
        }
  
        if (status & (F_HIPIODRBDROPERR | F_LOPIODRBDROPERR))
-               CH_ALERT(adapter, "SGE dropped %s priority doorbell\n",
-                        status & F_HIPIODRBDROPERR ? "high" : "lo");
+               queue_work(cxgb3_wq, &adapter->db_drop_task);
+       if (status & (F_HIPRIORITYDBFULL | F_LOPRIORITYDBFULL))
+               queue_work(cxgb3_wq, &adapter->db_full_task);
+       if (status & (F_HIPRIORITYDBEMPTY | F_LOPRIORITYDBEMPTY))
+               queue_work(cxgb3_wq, &adapter->db_empty_task);
  
        t3_write_reg(adapter, A_SG_INT_CAUSE, status);
        if (status &  SGE_FATALERR)
index 3ab9f51918aa21e891c034d25323ed7077e3ec49,c38fc717a0d137384c0067ce03daf0a10dddc1c8..95a8ba0759f1aa61bf13517db07d94f644897443
@@@ -1262,8 -1262,7 +1262,8 @@@ void t3_link_changed(struct adapter *ad
                lc->fc = fc;
        }
  
 -      t3_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc);
 +      t3_os_link_changed(adapter, port_id, link_ok && !pi->link_fault,
 +                         speed, duplex, fc);
  }
  
  void t3_link_fault(struct adapter *adapter, int port_id)
@@@ -1433,7 -1432,10 +1433,10 @@@ static int t3_handle_intr_status(struc
                       F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
                       V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
                       F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
-                      F_HIRCQPARITYERROR)
+                      F_HIRCQPARITYERROR | F_LOPRIORITYDBFULL | \
+                      F_HIPRIORITYDBFULL | F_LOPRIORITYDBEMPTY | \
+                      F_HIPRIORITYDBEMPTY | F_HIPIODRBDROPERR | \
+                      F_LOPIODRBDROPERR)
  #define MC5_INTR_MASK (F_PARITYERR | F_ACTRGNFULL | F_UNKNOWNCMD | \
                       F_REQQPARERR | F_DISPQPARERR | F_DELACTEMPTY | \
                       F_NFASRCHFAIL)