diff options
Diffstat (limited to 'drivers/net/cxgb3')
-rw-r--r-- | drivers/net/cxgb3/adapter.h | 5 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 58 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_offload.c | 1 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_offload.h | 5 | ||||
-rw-r--r-- | drivers/net/cxgb3/l2t.c | 1 | ||||
-rw-r--r-- | drivers/net/cxgb3/regs.h | 16 | ||||
-rw-r--r-- | drivers/net/cxgb3/sge.c | 35 | ||||
-rw-r--r-- | drivers/net/cxgb3/t3_hw.c | 5 | ||||
-rw-r--r-- | drivers/net/cxgb3/xgmac.c | 8 |
9 files changed, 113 insertions, 21 deletions
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 3e8618b4efbc..4cd7f420766a 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -264,6 +264,10 @@ struct adapter { struct work_struct fatal_error_handler_task; struct work_struct link_fault_handler_task; + struct work_struct db_full_task; + struct work_struct db_empty_task; + struct work_struct db_drop_task; + struct dentry *debugfs_root; struct mutex mdio_lock; @@ -335,6 +339,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx, unsigned char *data); irqreturn_t t3_sge_intr_msix(int irq, void *cookie); +extern struct workqueue_struct *cxgb3_wq; int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index cecdec1551db..aced6c5e635c 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -45,6 +45,8 @@ #include <linux/firmware.h> #include <linux/log2.h> #include <linux/stringify.h> +#include <linux/sched.h> +#include <linux/slab.h> #include <asm/uaccess.h> #include "common.h" @@ -140,7 +142,7 @@ MODULE_PARM_DESC(ofld_disable, "whether to enable offload at init time or not"); * 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 @@ -586,6 +588,19 @@ static void setup_rss(struct adapter *adap) 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; @@ -2751,6 +2766,42 @@ static void t3_adap_check_task(struct work_struct *work) 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. */ @@ -3219,6 +3270,11 @@ static int __devinit init_one(struct pci_dev *pdev, 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 --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index 9498361119d6..c6485b39eb0e 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -31,6 +31,7 @@ */ #include <linux/list.h> +#include <linux/slab.h> #include <net/neighbour.h> #include <linux/notifier.h> #include <asm/atomic.h> diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h index 670aa62042da..929c298115ca 100644 --- a/drivers/net/cxgb3/cxgb3_offload.h +++ b/drivers/net/cxgb3/cxgb3_offload.h @@ -73,7 +73,10 @@ enum { OFFLOAD_STATUS_UP, OFFLOAD_STATUS_DOWN, OFFLOAD_PORT_DOWN, - OFFLOAD_PORT_UP + OFFLOAD_PORT_UP, + OFFLOAD_DB_FULL, + OFFLOAD_DB_EMPTY, + OFFLOAD_DB_DROP }; struct cxgb3_client { diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c index ff1611f90e7a..2f3ee721c3e1 100644 --- a/drivers/net/cxgb3/l2t.c +++ b/drivers/net/cxgb3/l2t.c @@ -34,6 +34,7 @@ #include <linux/if.h> #include <linux/if_vlan.h> #include <linux/jhash.h> +#include <linux/slab.h> #include <net/neighbour.h> #include "common.h" #include "t3cdev.h" diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index 1b5327b5a965..cb42353c9fdd 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -254,6 +254,22 @@ #define V_LOPIODRBDROPERR(x) ((x) << S_LOPIODRBDROPERR) #define F_LOPIODRBDROPERR V_LOPIODRBDROPERR(1U) +#define S_HIPRIORITYDBFULL 7 +#define V_HIPRIORITYDBFULL(x) ((x) << S_HIPRIORITYDBFULL) +#define F_HIPRIORITYDBFULL V_HIPRIORITYDBFULL(1U) + +#define S_HIPRIORITYDBEMPTY 6 +#define V_HIPRIORITYDBEMPTY(x) ((x) << S_HIPRIORITYDBEMPTY) +#define F_HIPRIORITYDBEMPTY V_HIPRIORITYDBEMPTY(1U) + +#define S_LOPRIORITYDBFULL 5 +#define V_LOPRIORITYDBFULL(x) ((x) << S_LOPRIORITYDBFULL) +#define F_LOPRIORITYDBFULL V_LOPRIORITYDBFULL(1U) + +#define S_LOPRIORITYDBEMPTY 4 +#define V_LOPRIORITYDBEMPTY(x) ((x) << S_LOPRIORITYDBEMPTY) +#define F_LOPRIORITYDBEMPTY V_LOPRIORITYDBEMPTY(1U) + #define S_RSPQDISABLED 3 #define V_RSPQDISABLED(x) ((x) << S_RSPQDISABLED) #define F_RSPQDISABLED V_RSPQDISABLED(1U) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 048205903741..5962b911b5bd 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -36,12 +36,14 @@ #include <linux/ip.h> #include <linux/tcp.h> #include <linux/dma-mapping.h> +#include <linux/slab.h> #include <net/arp.h> #include "common.h" #include "regs.h" #include "sge_defs.h" #include "t3_cpl.h" #include "firmware_exports.h" +#include "cxgb3_offload.h" #define USE_GTS 0 @@ -116,7 +118,7 @@ struct rx_sw_desc { /* SW state per Rx descriptor */ struct sk_buff *skb; struct fl_pg_chunk pg_chunk; }; - DECLARE_PCI_UNMAP_ADDR(dma_addr); + DEFINE_DMA_UNMAP_ADDR(dma_addr); }; struct rsp_desc { /* response queue descriptor */ @@ -196,17 +198,17 @@ static inline void refill_rspq(struct adapter *adapter, /** * need_skb_unmap - does the platform need unmapping of sk_buffs? * - * Returns true if the platfrom needs sk_buff unmapping. The compiler + * Returns true if the platform needs sk_buff unmapping. The compiler * optimizes away unecessary code if this returns true. */ static inline int need_skb_unmap(void) { /* - * This structure is used to tell if the platfrom needs buffer + * This structure is used to tell if the platform needs buffer * unmapping by checking if DECLARE_PCI_UNMAP_ADDR defines anything. */ struct dummy { - DECLARE_PCI_UNMAP_ADDR(addr); + DEFINE_DMA_UNMAP_ADDR(addr); }; return sizeof(struct dummy) != 0; @@ -361,7 +363,7 @@ static void clear_rx_desc(struct pci_dev *pdev, const struct sge_fl *q, put_page(d->pg_chunk.page); d->pg_chunk.page = NULL; } else { - pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr), + pci_unmap_single(pdev, dma_unmap_addr(d, dma_addr), q->buf_size, PCI_DMA_FROMDEVICE); kfree_skb(d->skb); d->skb = NULL; @@ -417,7 +419,7 @@ static inline int add_one_rx_buf(void *va, unsigned int len, if (unlikely(pci_dma_mapping_error(pdev, mapping))) return -ENOMEM; - pci_unmap_addr_set(sd, dma_addr, mapping); + dma_unmap_addr_set(sd, dma_addr, mapping); d->addr_lo = cpu_to_be32(mapping); d->addr_hi = cpu_to_be32((u64) mapping >> 32); @@ -513,7 +515,7 @@ nomem: q->alloc_failed++; break; } mapping = sd->pg_chunk.mapping + sd->pg_chunk.offset; - pci_unmap_addr_set(sd, dma_addr, mapping); + dma_unmap_addr_set(sd, dma_addr, mapping); add_one_rx_chunk(mapping, d, q->gen); pci_dma_sync_single_for_device(adap->pdev, mapping, @@ -789,11 +791,11 @@ static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl, if (likely(skb != NULL)) { __skb_put(skb, len); pci_dma_sync_single_for_cpu(adap->pdev, - pci_unmap_addr(sd, dma_addr), len, + dma_unmap_addr(sd, dma_addr), len, PCI_DMA_FROMDEVICE); memcpy(skb->data, sd->skb->data, len); pci_dma_sync_single_for_device(adap->pdev, - pci_unmap_addr(sd, dma_addr), len, + dma_unmap_addr(sd, dma_addr), len, PCI_DMA_FROMDEVICE); } else if (!drop_thres) goto use_orig_buf; @@ -808,7 +810,7 @@ recycle: goto recycle; use_orig_buf: - pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), + pci_unmap_single(adap->pdev, dma_unmap_addr(sd, dma_addr), fl->buf_size, PCI_DMA_FROMDEVICE); skb = sd->skb; skb_put(skb, len); @@ -841,7 +843,7 @@ static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, struct sk_buff *newskb, *skb; struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; - dma_addr_t dma_addr = pci_unmap_addr(sd, dma_addr); + dma_addr_t dma_addr = dma_unmap_addr(sd, dma_addr); newskb = skb = q->pg_skb; if (!skb && (len <= SGE_RX_COPY_THRES)) { @@ -2095,7 +2097,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, fl->credits--; pci_dma_sync_single_for_cpu(adap->pdev, - pci_unmap_addr(sd, dma_addr), + dma_unmap_addr(sd, dma_addr), fl->buf_size - SGE_PG_RSVD, PCI_DMA_FROMDEVICE); @@ -2841,8 +2843,13 @@ void t3_sge_err_intr_handler(struct adapter *adapter) } 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) diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 3ab9f51918aa..95a8ba0759f1 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -1433,7 +1433,10 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg, 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) diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index c142a2132e9f..3af19a550372 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -311,16 +311,16 @@ int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev) if (dev->flags & IFF_ALLMULTI) hash_lo = hash_hi = 0xffffffff; else { - struct dev_mc_list *dmi; + struct netdev_hw_addr *ha; int exact_addr_idx = mac->nucast; hash_lo = hash_hi = 0; - netdev_for_each_mc_addr(dmi, dev) + netdev_for_each_mc_addr(ha, dev) if (exact_addr_idx < EXACT_ADDR_FILTERS) set_addr_filter(mac, exact_addr_idx++, - dmi->dmi_addr); + ha->addr); else { - int hash = hash_hw_addr(dmi->dmi_addr); + int hash = hash_hw_addr(ha->addr); if (hash < 32) hash_lo |= (1 << hash); |