diff options
Diffstat (limited to 'drivers/net/benet')
-rw-r--r-- | drivers/net/benet/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/benet/be.h | 65 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.c | 681 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.h | 80 | ||||
-rw-r--r-- | drivers/net/benet/be_ethtool.c | 38 | ||||
-rw-r--r-- | drivers/net/benet/be_hw.h | 92 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 798 |
7 files changed, 1043 insertions, 712 deletions
diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig index c6934f179c0..fdb6e81a437 100644 --- a/drivers/net/benet/Kconfig +++ b/drivers/net/benet/Kconfig @@ -1,7 +1,6 @@ config BE2NET tristate "ServerEngines' 10Gbps NIC - BladeEngine 2" depends on PCI && INET - select INET_LRO help This driver implements the NIC functionality for ServerEngines' 10Gbps network adapter - BladeEngine 2. diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 5b4bf3d2cdc..684c6fe24c8 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -28,11 +28,11 @@ #include <linux/if_vlan.h> #include <linux/workqueue.h> #include <linux/interrupt.h> -#include <linux/inet_lro.h> +#include <linux/firmware.h> #include "be_hw.h" -#define DRV_VER "2.0.348" +#define DRV_VER "2.101.205" #define DRV_NAME "be2net" #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" #define OC_NAME "Emulex OneConnect 10Gbps NIC" @@ -72,8 +72,7 @@ static inline char *nic_name(struct pci_dev *pdev) #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) -#define BE_MAX_LRO_DESCRIPTORS 16 -#define BE_MAX_FRAGS_PER_FRAME (min((u32) 16, (u32) MAX_SKB_FRAGS)) +#define FW_VER_LEN 32 struct be_dma_mem { void *va; @@ -127,7 +126,6 @@ static inline void queue_tail_inc(struct be_queue_info *q) index_inc(&q->tail, q->len); } - struct be_eq_obj { struct be_queue_info q; char desc[32]; @@ -146,31 +144,6 @@ struct be_mcc_obj { struct be_queue_info cq; }; -struct be_ctrl_info { - u8 __iomem *csr; - u8 __iomem *db; /* Door Bell */ - u8 __iomem *pcicfg; /* PCI config space */ - int pci_func; - - /* Mbox used for cmd request/response */ - spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */ - struct be_dma_mem mbox_mem; - /* Mbox mem is adjusted to align to 16 bytes. The allocated addr - * is stored for freeing purpose */ - struct be_dma_mem mbox_mem_alloced; - - /* MCC Rings */ - struct be_mcc_obj mcc_obj; - spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ - spinlock_t mcc_cq_lock; - - /* MCC Async callback */ - void (*async_cb)(void *adapter, bool link_up); - void *adapter_ctxt; -}; - -#include "be_cmds.h" - struct be_drvr_stats { u32 be_tx_reqs; /* number of TX requests initiated */ u32 be_tx_stops; /* number of times TX Q was stopped */ @@ -189,8 +162,6 @@ struct be_drvr_stats { u32 be_polls; /* number of times NAPI called poll function */ u32 be_rx_events; /* number of ucast rx completion events */ u32 be_rx_compl; /* number of rx completion entries processed */ - u32 be_lro_hgram_data[8]; /* histogram of LRO data packets */ - u32 be_lro_hgram_ack[8]; /* histogram of LRO ACKs */ ulong be_rx_jiffies; u64 be_rx_bytes; u64 be_rx_bytes_prev; @@ -233,8 +204,6 @@ struct be_rx_obj { struct be_queue_info q; struct be_queue_info cq; struct be_rx_page_info page_info_tbl[RX_Q_LEN]; - struct net_lro_mgr lro_mgr; - struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS]; }; #define BE_NUM_MSIX_VECTORS 2 /* 1 each for Tx and Rx */ @@ -242,8 +211,19 @@ struct be_adapter { struct pci_dev *pdev; struct net_device *netdev; - /* Mbox, pci config, csr address information */ - struct be_ctrl_info ctrl; + u8 __iomem *csr; + u8 __iomem *db; /* Door Bell */ + u8 __iomem *pcicfg; /* PCI config space */ + + spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */ + struct be_dma_mem mbox_mem; + /* Mbox mem is adjusted to align to 16 bytes. The allocated addr + * is stored for freeing purpose */ + struct be_dma_mem mbox_mem_alloced; + + struct be_mcc_obj mcc_obj; + spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ + spinlock_t mcc_cq_lock; struct msix_entry msix_entries[BE_NUM_MSIX_VECTORS]; bool msix_enabled; @@ -271,7 +251,6 @@ struct be_adapter { /* Ethtool knobs and info */ bool rx_csum; /* BE card must perform rx-checksumming */ - u32 max_rx_coal; char fw_ver[FW_VER_LEN]; u32 if_handle; /* Used to configure filtering */ u32 pmac_id; /* MAC addr handle used by BE card */ @@ -281,10 +260,15 @@ struct be_adapter { bool promiscuous; }; -extern struct ethtool_ops be_ethtool_ops; +extern const struct ethtool_ops be_ethtool_ops; #define drvr_stats(adapter) (&adapter->stats.drvr_stats) +static inline unsigned int be_pci_func(struct be_adapter *adapter) +{ + return PCI_FUNC(adapter->pdev->devfn); +} + #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) #define PAGE_SHIFT_4K 12 @@ -375,6 +359,9 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) return val; } -extern void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm, +extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped); +extern void be_link_status_update(struct be_adapter *adapter, bool link_up); +extern void netdev_stats_update(struct be_adapter *adapter); +extern int be_load_fw(struct be_adapter *adapter, u8 *func); #endif /* BE_H */ diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 583517ed56f..3dd76c4170b 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -16,21 +16,22 @@ */ #include "be.h" +#include "be_cmds.h" -static void be_mcc_notify(struct be_ctrl_info *ctrl) +static void be_mcc_notify(struct be_adapter *adapter) { - struct be_queue_info *mccq = &ctrl->mcc_obj.q; + struct be_queue_info *mccq = &adapter->mcc_obj.q; u32 val = 0; val |= mccq->id & DB_MCCQ_RING_ID_MASK; val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; - iowrite32(val, ctrl->db + DB_MCCQ_OFFSET); + iowrite32(val, adapter->db + DB_MCCQ_OFFSET); } /* To check if valid bit is set, check the entire word as we don't know * the endianness of the data (old entry is host endian while a new entry is * little endian) */ -static inline bool be_mcc_compl_is_new(struct be_mcc_cq_entry *compl) +static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) { if (compl->flags != 0) { compl->flags = le32_to_cpu(compl->flags); @@ -42,13 +43,13 @@ static inline bool be_mcc_compl_is_new(struct be_mcc_cq_entry *compl) } /* Need to reset the entire word that houses the valid bit */ -static inline void be_mcc_compl_use(struct be_mcc_cq_entry *compl) +static inline void be_mcc_compl_use(struct be_mcc_compl *compl) { compl->flags = 0; } -static int be_mcc_compl_process(struct be_ctrl_info *ctrl, - struct be_mcc_cq_entry *compl) +static int be_mcc_compl_process(struct be_adapter *adapter, + struct be_mcc_compl *compl) { u16 compl_status, extd_status; @@ -58,23 +59,30 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & CQE_STATUS_COMPL_MASK; - if (compl_status != MCC_STATUS_SUCCESS) { + if (compl_status == MCC_STATUS_SUCCESS) { + if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) { + struct be_cmd_resp_get_stats *resp = + adapter->stats.cmd.va; + be_dws_le_to_cpu(&resp->hw_stats, + sizeof(resp->hw_stats)); + netdev_stats_update(adapter); + } + } else if (compl_status != MCC_STATUS_NOT_SUPPORTED) { extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & CQE_STATUS_EXTD_MASK; - printk(KERN_WARNING DRV_NAME - " error in cmd completion: status(compl/extd)=%d/%d\n", + dev_warn(&adapter->pdev->dev, + "Error in cmd completion: status(compl/extd)=%d/%d\n", compl_status, extd_status); - return -1; } - return 0; + return compl_status; } /* Link state evt is a string of bytes; no need for endian swapping */ -static void be_async_link_state_process(struct be_ctrl_info *ctrl, +static void be_async_link_state_process(struct be_adapter *adapter, struct be_async_event_link_state *evt) { - ctrl->async_cb(ctrl->adapter_ctxt, - evt->port_link_status == ASYNC_EVENT_LINK_UP ? true : false); + be_link_status_update(adapter, + evt->port_link_status == ASYNC_EVENT_LINK_UP); } static inline bool is_link_state_evt(u32 trailer) @@ -84,10 +92,10 @@ static inline bool is_link_state_evt(u32 trailer) ASYNC_EVENT_CODE_LINK_STATE); } -static struct be_mcc_cq_entry *be_mcc_compl_get(struct be_ctrl_info *ctrl) +static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) { - struct be_queue_info *mcc_cq = &ctrl->mcc_obj.cq; - struct be_mcc_cq_entry *compl = queue_tail_node(mcc_cq); + struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq; + struct be_mcc_compl *compl = queue_tail_node(mcc_cq); if (be_mcc_compl_is_new(compl)) { queue_tail_inc(mcc_cq); @@ -96,55 +104,64 @@ static struct be_mcc_cq_entry *be_mcc_compl_get(struct be_ctrl_info *ctrl) return NULL; } -void be_process_mcc(struct be_ctrl_info *ctrl) +int be_process_mcc(struct be_adapter *adapter) { - struct be_mcc_cq_entry *compl; - int num = 0; + struct be_mcc_compl *compl; + int num = 0, status = 0; - spin_lock_bh(&ctrl->mcc_cq_lock); - while ((compl = be_mcc_compl_get(ctrl))) { + spin_lock_bh(&adapter->mcc_cq_lock); + while ((compl = be_mcc_compl_get(adapter))) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) { /* Interpret flags as an async trailer */ BUG_ON(!is_link_state_evt(compl->flags)); /* Interpret compl as a async link evt */ - be_async_link_state_process(ctrl, + be_async_link_state_process(adapter, (struct be_async_event_link_state *) compl); - } else { - be_mcc_compl_process(ctrl, compl); - atomic_dec(&ctrl->mcc_obj.q.used); + } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { + status = be_mcc_compl_process(adapter, compl); + atomic_dec(&adapter->mcc_obj.q.used); } be_mcc_compl_use(compl); num++; } + if (num) - be_cq_notify(ctrl, ctrl->mcc_obj.cq.id, true, num); - spin_unlock_bh(&ctrl->mcc_cq_lock); + be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, num); + + spin_unlock_bh(&adapter->mcc_cq_lock); + return status; } /* Wait till no more pending mcc requests are present */ -static void be_mcc_wait_compl(struct be_ctrl_info *ctrl) +static int be_mcc_wait_compl(struct be_adapter *adapter) { -#define mcc_timeout 50000 /* 5s timeout */ - int i; +#define mcc_timeout 120000 /* 12s timeout */ + int i, status; for (i = 0; i < mcc_timeout; i++) { - be_process_mcc(ctrl); - if (atomic_read(&ctrl->mcc_obj.q.used) == 0) + status = be_process_mcc(adapter); + if (status) + return status; + + if (atomic_read(&adapter->mcc_obj.q.used) == 0) break; udelay(100); } - if (i == mcc_timeout) - printk(KERN_WARNING DRV_NAME "mcc poll timed out\n"); + if (i == mcc_timeout) { + dev_err(&adapter->pdev->dev, "mccq poll timed out\n"); + return -1; + } + return 0; } /* Notify MCC requests and wait for completion */ -static void be_mcc_notify_wait(struct be_ctrl_info *ctrl) +static int be_mcc_notify_wait(struct be_adapter *adapter) { - be_mcc_notify(ctrl); - be_mcc_wait_compl(ctrl); + be_mcc_notify(adapter); + return be_mcc_wait_compl(adapter); } -static int be_mbox_db_ready_wait(void __iomem *db) +static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) { int cnt = 0, wait = 5; u32 ready; @@ -154,9 +171,8 @@ static int be_mbox_db_ready_wait(void __iomem *db) if (ready) break; - if (cnt > 200000) { - printk(KERN_WARNING DRV_NAME - ": mbox_db poll timed out\n"); + if (cnt > 4000000) { + dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); return -1; } @@ -173,55 +189,50 @@ static int be_mbox_db_ready_wait(void __iomem *db) * Insert the mailbox address into the doorbell in two steps * Polls on the mbox doorbell till a command completion (or a timeout) occurs */ -static int be_mbox_db_ring(struct be_ctrl_info *ctrl) +static int be_mbox_notify_wait(struct be_adapter *adapter) { int status; u32 val = 0; - void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; - struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; + void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET; + struct be_dma_mem *mbox_mem = &adapter->mbox_mem; struct be_mcc_mailbox *mbox = mbox_mem->va; - struct be_mcc_cq_entry *cqe = &mbox->cqe; - - memset(cqe, 0, sizeof(*cqe)); + struct be_mcc_compl *compl = &mbox->compl; - val &= ~MPU_MAILBOX_DB_RDY_MASK; val |= MPU_MAILBOX_DB_HI_MASK; /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; iowrite32(val, db); /* wait for ready to be set */ - status = be_mbox_db_ready_wait(db); + status = be_mbox_db_ready_wait(adapter, db); if (status != 0) return status; val = 0; - val &= ~MPU_MAILBOX_DB_RDY_MASK; - val &= ~MPU_MAILBOX_DB_HI_MASK; /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ val |= (u32)(mbox_mem->dma >> 4) << 2; iowrite32(val, db); - status = be_mbox_db_ready_wait(db); + status = be_mbox_db_ready_wait(adapter, db); if (status != 0) return status; /* A cq entry has been made now */ - if (be_mcc_compl_is_new(cqe)) { - status = be_mcc_compl_process(ctrl, &mbox->cqe); - be_mcc_compl_use(cqe); + if (be_mcc_compl_is_new(compl)) { + status = be_mcc_compl_process(adapter, &mbox->compl); + be_mcc_compl_use(compl); if (status) return status; } else { - printk(KERN_WARNING DRV_NAME "invalid mailbox completion\n"); + dev_err(&adapter->pdev->dev, "invalid mailbox completion\n"); return -1; } return 0; } -static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage) +static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage) { - u32 sem = ioread32(ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + u32 sem = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET); *stage = sem & EP_SEMAPHORE_POST_STAGE_MASK; if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK) @@ -230,54 +241,17 @@ static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage) return 0; } -static int be_POST_stage_poll(struct be_ctrl_info *ctrl, u16 poll_stage) -{ - u16 stage, cnt, error; - for (cnt = 0; cnt < 5000; cnt++) { - error = be_POST_stage_get(ctrl, &stage); - if (error) - return -1; - - if (stage == poll_stage) - break; - udelay(1000); - } - if (stage != poll_stage) - return -1; - return 0; -} - - -int be_cmd_POST(struct be_ctrl_info *ctrl) +int be_cmd_POST(struct be_adapter *adapter) { u16 stage, error; - error = be_POST_stage_get(ctrl, &stage); - if (error) - goto err; - - if (stage == POST_STAGE_ARMFW_RDY) - return 0; - - if (stage != POST_STAGE_AWAITING_HOST_RDY) - goto err; - - /* On awaiting host rdy, reset and again poll on awaiting host rdy */ - iowrite32(POST_STAGE_BE_RESET, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); - error = be_POST_stage_poll(ctrl, POST_STAGE_AWAITING_HOST_RDY); - if (error) - goto err; - - /* Now kickoff POST and poll on armfw ready */ - iowrite32(POST_STAGE_HOST_RDY, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); - error = be_POST_stage_poll(ctrl, POST_STAGE_ARMFW_RDY); - if (error) - goto err; + error = be_POST_stage_get(adapter, &stage); + if (error || stage != POST_STAGE_ARMFW_RDY) { + dev_err(&adapter->pdev->dev, "POST failed.\n"); + return -1; + } return 0; -err: - printk(KERN_WARNING DRV_NAME ": ERROR, stage=%d\n", stage); - return -1; } static inline void *embedded_payload(struct be_mcc_wrb *wrb) @@ -350,34 +324,40 @@ static u32 eq_delay_to_mult(u32 usec_delay) return multiplier; } -static inline struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) +static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter) { - return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; + struct be_dma_mem *mbox_mem = &adapter->mbox_mem; + struct be_mcc_wrb *wrb + = &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; + memset(wrb, 0, sizeof(*wrb)); + return wrb; } -static inline struct be_mcc_wrb *wrb_from_mcc(struct be_queue_info *mccq) +static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) { - struct be_mcc_wrb *wrb = NULL; - if (atomic_read(&mccq->used) < mccq->len) { - wrb = queue_head_node(mccq); - queue_head_inc(mccq); - atomic_inc(&mccq->used); - memset(wrb, 0, sizeof(*wrb)); - } + struct be_queue_info *mccq = &adapter->mcc_obj.q; + struct be_mcc_wrb *wrb; + + BUG_ON(atomic_read(&mccq->used) >= mccq->len); + wrb = queue_head_node(mccq); + queue_head_inc(mccq); + atomic_inc(&mccq->used); + memset(wrb, 0, sizeof(*wrb)); return wrb; } -int be_cmd_eq_create(struct be_ctrl_info *ctrl, +int be_cmd_eq_create(struct be_adapter *adapter, struct be_queue_info *eq, int eq_delay) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_eq_create *req = embedded_payload(wrb); - struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_eq_create *req; struct be_dma_mem *q_mem = &eq->dma_mem; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -387,7 +367,7 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl, req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); AMAP_SET_BITS(struct amap_eq_context, func, req->context, - ctrl->pci_func); + be_pci_func(adapter)); AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); /* 4byte eqe*/ AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); @@ -399,25 +379,29 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl, be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_db_ring(ctrl); + status = be_mbox_notify_wait(adapter); if (!status) { + struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); eq->id = le16_to_cpu(resp->eq_id); eq->created = true; } - spin_unlock(&ctrl->mbox_lock); + + spin_unlock(&adapter->mbox_lock); return status; } -int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, +/* Uses mbox */ +int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, u8 type, bool permanent, u32 if_handle) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_mac_query *req = embedded_payload(wrb); - struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_mac_query *req; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -428,27 +412,32 @@ int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, if (permanent) { req->permanent = 1; } else { - req->if_id = cpu_to_le16((u16)if_handle); + req->if_id = cpu_to_le16((u16) if_handle); req->permanent = 0; } - status = be_mbox_db_ring(ctrl); - if (!status) + status = be_mbox_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); memcpy(mac_addr, resp->mac.addr, ETH_ALEN); + } - spin_unlock(&ctrl->mbox_lock); + spin_unlock(&adapter->mbox_lock); return status; } -int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, +/* Uses synchronous MCCQ */ +int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, u32 if_id, u32 *pmac_id) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_pmac_add *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_pmac_add *req; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -458,24 +447,27 @@ int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, req->if_id = cpu_to_le32(if_id); memcpy(req->mac_address, mac_addr, ETH_ALEN); - status = be_mbox_db_ring(ctrl); + status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb); *pmac_id = le32_to_cpu(resp->pmac_id); } - spin_unlock(&ctrl->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } -int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id) +/* Uses synchronous MCCQ */ +int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_pmac_del *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_pmac_del *req; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -485,25 +477,29 @@ int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id) req->if_id = cpu_to_le32(if_id); req->pmac_id = cpu_to_le32(pmac_id); - status = be_mbox_db_ring(ctrl); - spin_unlock(&ctrl->mbox_lock); + status = be_mcc_notify_wait(adapter); + + spin_unlock_bh(&adapter->mcc_lock); return status; } -int be_cmd_cq_create(struct be_ctrl_info *ctrl, +/* Uses Mbox */ +int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, struct be_queue_info *eq, bool sol_evts, bool no_delay, int coalesce_wm) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_cq_create *req = embedded_payload(wrb); - struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_cq_create *req; struct be_dma_mem *q_mem = &cq->dma_mem; - void *ctxt = &req->context; + void *ctxt; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + ctxt = &req->context; be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -521,17 +517,19 @@ int be_cmd_cq_create(struct be_ctrl_info *ctrl, AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); - AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func); + AMAP_SET_BITS(struct amap_cq_context, func, ctxt, be_pci_func(adapter)); be_dws_cpu_to_le(ctxt, sizeof(req->context)); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_db_ring(ctrl); + status = be_mbox_notify_wait(adapter); if (!status) { + struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); cq->id = le16_to_cpu(resp->cq_id); cq->created = true; } - spin_unlock(&ctrl->mbox_lock); + + spin_unlock(&adapter->mbox_lock); return status; } @@ -544,18 +542,21 @@ static u32 be_encoded_q_len(int q_len) return len_encoded; } -int be_cmd_mccq_create(struct be_ctrl_info *ctrl, +int be_cmd_mccq_create(struct be_adapter *adapter, struct be_queue_info *mccq, struct be_queue_info *cq) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_mcc_create *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_mcc_create *req; struct be_dma_mem *q_mem = &mccq->dma_mem; - void *ctxt = &req->context; + void *ctxt; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + ctxt = &req->context; be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -564,7 +565,7 @@ int be_cmd_mccq_create(struct be_ctrl_info *ctrl, req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); - AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, ctrl->pci_func); + AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, be_pci_func(adapter)); AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, be_encoded_q_len(mccq->len)); @@ -574,30 +575,32 @@ int be_cmd_mccq_create(struct be_ctrl_info *ctrl, be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_db_ring(ctrl); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); mccq->id = le16_to_cpu(resp->id); mccq->created = true; } - spin_unlock(&ctrl->mbox_lock); + spin_unlock(&adapter->mbox_lock); return status; } -int be_cmd_txq_create(struct be_ctrl_info *ctrl, +int be_cmd_txq_create(struct be_adapter *adapter, struct be_queue_info *txq, struct be_queue_info *cq) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_eth_tx_create *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_eth_tx_create *req; struct be_dma_mem *q_mem = &txq->dma_mem; - void *ctxt = &req->context; + void *ctxt; int status; - u32 len_encoded; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + ctxt = &req->context; be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -608,12 +611,10 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl, req->ulp_num = BE_ULP1_NUM; req->type = BE_ETH_TX_RING_TYPE_STANDARD; - len_encoded = fls(txq->len); /* log2(len) + 1 */ - if (len_encoded == 16) - len_encoded = 0; - AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, len_encoded); + AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, + be_encoded_q_len(txq->len)); AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt, - ctrl->pci_func); + be_pci_func(adapter)); AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1); AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id); @@ -621,28 +622,32 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl, be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_db_ring(ctrl); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb); txq->id = le16_to_cpu(resp->cid); txq->created = true; } - spin_unlock(&ctrl->mbox_lock); + + spin_unlock(&adapter->mbox_lock); return status; } -int be_cmd_rxq_create(struct be_ctrl_info *ctrl, +/* Uses mbox */ +int be_cmd_rxq_create(struct be_adapter *adapter, struct be_queue_info *rxq, u16 cq_id, u16 frag_size, u16 max_frame_size, u32 if_id, u32 rss) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_eth_rx_create *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_eth_rx_create *req; struct be_dma_mem *q_mem = &rxq->dma_mem; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -657,29 +662,34 @@ int be_cmd_rxq_create(struct be_ctrl_info *ctrl, req->max_frame_size = cpu_to_le16(max_frame_size); req->rss_queue = cpu_to_le32(rss); - status = be_mbox_db_ring(ctrl); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); rxq->id = le16_to_cpu(resp->id); rxq->created = true; } - spin_unlock(&ctrl->mbox_lock); + + spin_unlock(&adapter->mbox_lock); return status; } -/* Generic destroyer function for all types of queues */ -int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, +/* Generic destroyer function for all types of queues + * Uses Mbox + */ +int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, int queue_type) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_q_destroy *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_q_destroy *req; u8 subsys = 0, opcode = 0; int status; - spin_lock(&ctrl->mbox_lock); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); - memset(wrb, 0, sizeof(*wrb)); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); switch (queue_type) { @@ -704,30 +714,32 @@ int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, opcode = OPCODE_COMMON_MCC_DESTROY; break; default: - printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n"); - status = -1; - goto err; + BUG(); } be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); req->id = cpu_to_le16(q->id); - status = be_mbox_db_ring(ctrl); -err: - spin_unlock(&ctrl->mbox_lock); + status = be_mbox_notify_wait(adapter); + + spin_unlock(&adapter->mbox_lock); return status; } -/* Create an rx filtering policy configuration on an i/f */ -int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, +/* Create an rx filtering policy configuration on an i/f + * Uses mbox + */ +int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac, bool pmac_invalid, u32 *if_handle, u32 *pmac_id) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_if_create *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_if_create *req; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -736,10 +748,11 @@ int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, req->capability_flags = cpu_to_le32(flags); req->enable_flags = cpu_to_le32(flags); + req->pmac_invalid = pmac_invalid; if (!pmac_invalid) memcpy(req->mac_addr, mac, ETH_ALEN); - status = be_mbox_db_ring(ctrl); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_if_create *resp = embedded_payload(wrb); *if_handle = le32_to_cpu(resp->interface_id); @@ -747,18 +760,21 @@ int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, *pmac_id = le32_to_cpu(resp->pmac_id); } - spin_unlock(&ctrl->mbox_lock); + spin_unlock(&adapter->mbox_lock); return status; } -int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id) +/* Uses mbox */ +int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_if_destroy *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_if_destroy *req; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -766,29 +782,32 @@ int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id) OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req)); req->interface_id = cpu_to_le32(interface_id); - status = be_mbox_db_ring(ctrl); - spin_unlock(&ctrl->mbox_lock); + status = be_mbox_notify_wait(adapter); + + spin_unlock(&adapter->mbox_lock); return status; } /* Get stats is a non embedded command: the request is not embedded inside * WRB but is a separate dma memory block + * Uses asynchronous MCC */ -int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd) +int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_get_stats *req = nonemb_cmd->va; - struct be_sge *sge = nonembedded_sgl(wrb); - int status; + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_stats *req; + struct be_sge *sge; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); - memset(req, 0, sizeof(*req)); + wrb = wrb_from_mccq(adapter); + req = nonemb_cmd->va; + sge = nonembedded_sgl(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); + wrb->tag0 = OPCODE_ETH_GET_STATISTICS; be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_GET_STATISTICS, sizeof(*req)); @@ -796,77 +815,82 @@ int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd) sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); sge->len = cpu_to_le32(nonemb_cmd->size); - status = be_mbox_db_ring(ctrl); - if (!status) { - struct be_cmd_resp_get_stats *resp = nonemb_cmd->va; - be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); - } + be_mcc_notify(adapter); - spin_unlock(&ctrl->mbox_lock); - return status; + spin_unlock_bh(&adapter->mcc_lock); + return 0; } -int be_cmd_link_status_query(struct be_ctrl_info *ctrl, +/* Uses synchronous mcc */ +int be_cmd_link_status_query(struct be_adapter *adapter, bool *link_up) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_link_status *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_link_status *req; int status; - spin_lock(&ctrl->mbox_lock); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); *link_up = false; - memset(wrb, 0, sizeof(*wrb)); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req)); - status = be_mbox_db_ring(ctrl); + status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_link_status *resp = embedded_payload(wrb); if (resp->mac_speed != PHY_LINK_SPEED_ZERO) *link_up = true; } - spin_unlock(&ctrl->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } -int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver) +/* Uses Mbox */ +int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_get_fw_version *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_fw_version *req; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_GET_FW_VERSION, sizeof(*req)); - status = be_mbox_db_ring(ctrl); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb); strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN); } - spin_unlock(&ctrl->mbox_lock); + spin_unlock(&adapter->mbox_lock); return status; } -/* set the EQ delay interval of an EQ to specified value */ -int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd) +/* set the EQ delay interval of an EQ to specified value + * Uses async mcc + */ +int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb); - int status; + struct be_mcc_wrb *wrb; + struct be_cmd_req_modify_eq_delay *req; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -878,21 +902,24 @@ int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd) req->delay[0].phase = 0; req->delay[0].delay_multiplier = cpu_to_le32(eqd); - status = be_mbox_db_ring(ctrl); + be_mcc_notify(adapter); - spin_unlock(&ctrl->mbox_lock); - return status; + spin_unlock_bh(&adapter->mcc_lock); + return 0; } -int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array, +/* Uses sycnhronous mcc */ +int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, u32 num, bool untagged, bool promiscuous) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_vlan_config *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_vlan_config *req; int status; - spin_lock(&ctrl->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -908,23 +935,24 @@ int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array, req->num_vlan * sizeof(vtag_array[0])); } - status = be_mbox_db_ring(ctrl); + status = be_mcc_notify_wait(adapter); - spin_unlock(&ctrl->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } -/* Use MCC for this command as it may be called in BH context */ -int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) +/* Uses MCC for this command as it may be called in BH context + * Uses synchronous mcc + */ +int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) { struct be_mcc_wrb *wrb; struct be_cmd_req_promiscuous_config *req; + int status; - spin_lock_bh(&ctrl->mcc_lock); - - wrb = wrb_from_mcc(&ctrl->mcc_obj.q); - BUG_ON(!wrb); + spin_lock_bh(&adapter->mcc_lock); + wrb = wrb_from_mccq(adapter); req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -937,28 +965,26 @@ int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) else req->port0_promiscuous = en; - be_mcc_notify_wait(ctrl); + status = be_mcc_notify_wait(adapter); - spin_unlock_bh(&ctrl->mcc_lock); - return 0; + spin_unlock_bh(&adapter->mcc_lock); + return status; } /* - * Use MCC for this command as it may be called in BH context + * Uses MCC for this command as it may be called in BH context * (mc == NULL) => multicast promiscous */ -int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id, +int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, struct dev_mc_list *mc_list, u32 mc_count) { #define BE_MAX_MC 32 /* set mcast promisc if > 32 */ struct be_mcc_wrb *wrb; struct be_cmd_req_mcast_mac_config *req; - spin_lock_bh(&ctrl->mcc_lock); - - wrb = wrb_from_mcc(&ctrl->mcc_obj.q); - BUG_ON(!wrb); + spin_lock_bh(&adapter->mcc_lock); + wrb = wrb_from_mccq(adapter); req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -979,22 +1005,24 @@ int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id, req->promiscuous = 1; } - be_mcc_notify_wait(ctrl); + be_mcc_notify_wait(adapter); - spin_unlock_bh(&ctrl->mcc_lock); + spin_unlock_bh(&adapter->mcc_lock); return 0; } -int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) +/* Uses synchrounous mcc */ +int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_set_flow_control *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_set_flow_control *req; int status; - spin_lock(&ctrl->mbox_lock); + spin_lock_bh(&adapter->mcc_lock); - memset(wrb, 0, sizeof(*wrb)); + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -1004,28 +1032,30 @@ int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) req->tx_flow_control = cpu_to_le16((u16)tx_fc); req->rx_flow_control = cpu_to_le16((u16)rx_fc); - status = be_mbox_db_ring(ctrl); + status = be_mcc_notify_wait(adapter); - spin_unlock(&ctrl->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } -int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc) +/* Uses sycn mcc */ +int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_get_flow_control *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_flow_control *req; int status; - spin_lock(&ctrl->mbox_lock); + spin_lock_bh(&adapter->mcc_lock); - memset(wrb, 0, sizeof(*wrb)); + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req)); - status = be_mbox_db_ring(ctrl); + status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_get_flow_control *resp = embedded_payload(wrb); @@ -1033,31 +1063,88 @@ int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc) *rx_fc = le16_to_cpu(resp->rx_flow_control); } - spin_unlock(&ctrl->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } -int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num) +/* Uses mbox */ +int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_query_fw_cfg *req; int status; - spin_lock(&ctrl->mbox_lock); + spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); - status = be_mbox_db_ring(ctrl); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); *port_num = le32_to_cpu(resp->phys_port); } - spin_unlock(&ctrl->mbox_lock); + spin_unlock(&adapter->mbox_lock); + return status; +} + +/* Uses mbox */ +int be_cmd_reset_function(struct be_adapter *adapter) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_hdr *req; + int status; + + spin_lock(&adapter->mbox_lock); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_FUNCTION_RESET, sizeof(*req)); + + status = be_mbox_notify_wait(adapter); + + spin_unlock(&adapter->mbox_lock); + return status; +} + +int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, + u32 flash_type, u32 flash_opcode, u32 buf_size) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_write_flashrom *req = cmd->va; + struct be_sge *sge; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); + sge = nonembedded_sgl(wrb); + + be_wrb_hdr_prepare(wrb, cmd->size, false, 1); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_WRITE_FLASHROM, cmd->size); + sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma)); + sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(cmd->size); + + req->params.op_type = cpu_to_le32(flash_type); + req->params.op_code = cpu_to_le32(flash_opcode); + req->params.data_buf_size = cpu_to_le32(buf_size); + + status = be_mcc_notify_wait(adapter); + + spin_unlock_bh(&adapter->mcc_lock); return status; } diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 747626da7b4..93e432f3d92 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -61,7 +61,8 @@ enum { /* The command is completing because the queue was getting flushed */ MCC_STATUS_QUEUE_FLUSHING = 0x4, /* The command is completing with a DMA error */ - MCC_STATUS_DMA_FAILED = 0x5 + MCC_STATUS_DMA_FAILED = 0x5, + MCC_STATUS_NOT_SUPPORTED = 0x66 }; #define CQE_STATUS_COMPL_MASK 0xFFFF @@ -69,7 +70,7 @@ enum { #define CQE_STATUS_EXTD_MASK 0xFFFF #define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */ -struct be_mcc_cq_entry { +struct be_mcc_compl { u32 status; /* dword 0 */ u32 tag0; /* dword 1 */ u32 tag1; /* dword 2 */ @@ -106,7 +107,7 @@ struct be_async_event_link_state { struct be_mcc_mailbox { struct be_mcc_wrb wrb; - struct be_mcc_cq_entry cqe; + struct be_mcc_compl compl; }; #define CMD_SUBSYSTEM_COMMON 0x1 @@ -117,6 +118,7 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_NTWK_MULTICAST_SET 3 #define OPCODE_COMMON_NTWK_VLAN_CONFIG 4 #define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5 +#define OPCODE_COMMON_WRITE_FLASHROM 7 #define OPCODE_COMMON_CQ_CREATE 12 #define OPCODE_COMMON_EQ_CREATE 13 #define OPCODE_COMMON_MCC_CREATE 21 @@ -135,6 +137,7 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 #define OPCODE_COMMON_NTWK_PMAC_ADD 59 #define OPCODE_COMMON_NTWK_PMAC_DEL 60 +#define OPCODE_COMMON_FUNCTION_RESET 61 #define OPCODE_ETH_ACPI_CONFIG 2 #define OPCODE_ETH_PROMISCUOUS 3 @@ -634,7 +637,6 @@ struct be_cmd_resp_link_status { } __packed; /******************** Get FW Version *******************/ -#define FW_VER_LEN 32 struct be_cmd_req_get_fw_version { struct be_cmd_req_hdr hdr; u8 rsvd0[FW_VER_LEN]; @@ -693,56 +695,74 @@ struct be_cmd_resp_query_fw_cfg { u32 be_config_number; u32 asic_revision; u32 phys_port; - u32 function_mode; + u32 function_cap; u32 rsvd[26]; }; -extern int be_pci_fnum_get(struct be_ctrl_info *ctrl); -extern int be_cmd_POST(struct be_ctrl_info *ctrl); -extern int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, +/****************** Firmware Flash ******************/ +struct flashrom_params { + u32 op_code; + u32 op_type; + u32 data_buf_size; + u32 offset; + u8 data_buf[4]; +}; + +struct be_cmd_write_flashrom { + struct be_cmd_req_hdr hdr; + struct flashrom_params params; +}; + +extern int be_pci_fnum_get(struct be_adapter *adapter); +extern int be_cmd_POST(struct be_adapter *adapter); +extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, u8 type, bool permanent, u32 if_handle); -extern int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, +extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, u32 if_id, u32 *pmac_id); -extern int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id); -extern int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 if_flags, u8 *mac, +extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id); +extern int be_cmd_if_create(struct be_adapter *adapter, u32 if_flags, u8 *mac, bool pmac_invalid, u32 *if_handle, u32 *pmac_id); -extern int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 if_handle); -extern int be_cmd_eq_create(struct be_ctrl_info *ctrl, +extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle); +extern int be_cmd_eq_create(struct be_adapter *adapter, struct be_queue_info *eq, int eq_delay); -extern int be_cmd_cq_create(struct be_ctrl_info *ctrl, +extern int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, struct be_queue_info *eq, bool sol_evts, bool no_delay, int num_cqe_dma_coalesce); -extern int be_cmd_mccq_create(struct be_ctrl_info *ctrl, +extern int be_cmd_mccq_create(struct be_adapter *adapter, struct be_queue_info *mccq, struct be_queue_info *cq); -extern int be_cmd_txq_create(struct be_ctrl_info *ctrl, +extern int be_cmd_txq_create(struct be_adapter *adapter, struct be_queue_info *txq, struct be_queue_info *cq); -extern int be_cmd_rxq_create(struct be_ctrl_info *ctrl, +extern int be_cmd_rxq_create(struct be_adapter *adapter, struct be_queue_info *rxq, u16 cq_id, u16 frag_size, u16 max_frame_size, u32 if_id, u32 rss); -extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, +extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, int type); -extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl, +extern int be_cmd_link_status_query(struct be_adapter *adapter, bool *link_up); -extern int be_cmd_reset(struct be_ctrl_info *ctrl); -extern int be_cmd_get_stats(struct be_ctrl_info *ctrl, +extern int be_cmd_reset(struct be_adapter *adapter); +extern int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd); -extern int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver); +extern int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver); -extern int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd); -extern int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, +extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd); +extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, u32 num, bool untagged, bool promiscuous); -extern int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, +extern int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en); -extern int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id, +extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, struct dev_mc_list *mc_list, u32 mc_count); -extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, +extern int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc); -extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, +extern int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc); -extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num); -extern void be_process_mcc(struct be_ctrl_info *ctrl); +extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num); +extern int be_cmd_reset_function(struct be_adapter *adapter); +extern int be_process_mcc(struct be_adapter *adapter); +extern int be_cmd_write_flashrom(struct be_adapter *adapter, + struct be_dma_mem *cmd, u32 flash_oper, + u32 flash_opcode, u32 buf_size); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index cccc5419ad7..11445df3dbc 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -16,6 +16,7 @@ */ #include "be.h" +#include "be_cmds.h" #include <linux/ethtool.h> struct be_ethtool_stat { @@ -127,8 +128,6 @@ be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq; - coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; - coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; @@ -144,14 +143,12 @@ be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) } /* - * This routine is used to set interrup coalescing delay *as well as* - * the number of pkts to coalesce for LRO. + * This routine is used to set interrup coalescing delay */ static int be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_ctrl_info *ctrl = &adapter->ctrl; struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq; u32 tx_max, tx_min, tx_cur; @@ -161,10 +158,6 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) if (coalesce->use_adaptive_tx_coalesce == 1) return -EINVAL; - adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; - if (adapter->max_rx_coal > BE_MAX_FRAGS_PER_FRAME) - adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME; - /* if AIC is being turned on now, start with an EQD of 0 */ if (rx_eq->enable_aic == 0 && coalesce->use_adaptive_rx_coalesce == 1) { @@ -183,7 +176,7 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) if (tx_cur > BE_MAX_EQD) tx_cur = BE_MAX_EQD; if (tx_eq->cur_eqd != tx_cur) { - status = be_cmd_modify_eqd(ctrl, tx_eq->q.id, tx_cur); + status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur); if (!status) tx_eq->cur_eqd = tx_cur; } @@ -203,7 +196,8 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) if (rx_cur > BE_MAX_EQD) rx_cur = BE_MAX_EQD; if (rx_eq->cur_eqd != rx_cur) { - status = be_cmd_modify_eqd(ctrl, rx_eq->q.id, rx_cur); + status = be_cmd_modify_eqd(adapter, rx_eq->q.id, + rx_cur); if (!status) rx_eq->cur_eqd = rx_cur; } @@ -317,8 +311,7 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) { struct be_adapter *adapter = netdev_priv(netdev); - be_cmd_get_flow_control(&adapter->ctrl, &ecmd->tx_pause, - &ecmd->rx_pause); + be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause); ecmd->autoneg = 0; } @@ -331,7 +324,7 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) if (ecmd->autoneg != 0) return -EINVAL; - status = be_cmd_set_flow_control(&adapter->ctrl, ecmd->tx_pause, + status = be_cmd_set_flow_control(adapter, ecmd->tx_pause, ecmd->rx_pause); if (!status) dev_warn(&adapter->pdev->dev, "Pause param set failed.\n"); @@ -339,7 +332,21 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) return status; } -struct ethtool_ops be_ethtool_ops = { +static int +be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) +{ + struct be_adapter *adapter = netdev_priv(netdev); + char file_name[ETHTOOL_FLASH_MAX_FILENAME]; + u32 region; + + file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0; + strcpy(file_name, efl->data); + region = efl->region; + + return be_load_fw(adapter, file_name); +} + +const struct ethtool_ops be_ethtool_ops = { .get_settings = be_get_settings, .get_drvinfo = be_get_drvinfo, .get_link = ethtool_op_get_link, @@ -359,4 +366,5 @@ struct ethtool_ops be_ethtool_ops = { .get_strings = be_get_stat_strings, .get_stats_count = be_get_stats_count, .get_ethtool_stats = be_get_ethtool_stats, + .flash_device = be_do_flash, }; diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index b02e805c1db..a3394b4aa14 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -51,9 +51,10 @@ * with the OS. */ #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ -/* PCI physical function number */ -#define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */ -#define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26 + +/********* ISR0 Register offset **********/ +#define CEV_ISR0_OFFSET 0xC18 +#define CEV_ISR_SIZE 4 /********* Event Q door bell *************/ #define DB_EQ_OFFSET DB_CQ_OFFSET @@ -203,7 +204,7 @@ struct amap_eth_rx_compl { u8 numfrags[3]; /* dword 1 */ u8 rss_flush; /* dword 2 */ u8 cast_enc[2]; /* dword 2 */ - u8 qnq; /* dword 2 */ + u8 vtm; /* dword 2 */ u8 rss_bank; /* dword 2 */ u8 rsvd1[23]; /* dword 2 */ u8 lro_pkt; /* dword 2 */ @@ -215,3 +216,86 @@ struct amap_eth_rx_compl { struct be_eth_rx_compl { u32 dw[4]; }; + +/* Flashrom related descriptors */ +#define IMAGE_TYPE_FIRMWARE 160 +#define IMAGE_TYPE_BOOTCODE 224 +#define IMAGE_TYPE_OPTIONROM 32 + +#define NUM_FLASHDIR_ENTRIES 32 + +#define FLASHROM_TYPE_ISCSI_ACTIVE 0 +#define FLASHROM_TYPE_BIOS 2 +#define FLASHROM_TYPE_PXE_BIOS 3 +#define FLASHROM_TYPE_FCOE_BIOS 8 +#define FLASHROM_TYPE_ISCSI_BACKUP 9 +#define FLASHROM_TYPE_FCOE_FW_ACTIVE 10 +#define FLASHROM_TYPE_FCOE_FW_BACKUP 11 + +#define FLASHROM_OPER_FLASH 1 +#define FLASHROM_OPER_SAVE 2 + +#define FLASH_IMAGE_MAX_SIZE (1310720) /* Max firmware image size */ +#define FLASH_BIOS_IMAGE_MAX_SIZE (262144) /* Max OPTION ROM image sz */ + +/* Offsets for components on Flash. */ +#define FLASH_iSCSI_PRIMARY_IMAGE_START (1048576) +#define FLASH_iSCSI_BACKUP_IMAGE_START (2359296) +#define FLASH_FCoE_PRIMARY_IMAGE_START (3670016) +#define FLASH_FCoE_BACKUP_IMAGE_START (4980736) +#define FLASH_iSCSI_BIOS_START (7340032) +#define FLASH_PXE_BIOS_START (7864320) +#define FLASH_FCoE_BIOS_START (524288) + +struct controller_id { + u32 vendor; + u32 device; + u32 subvendor; + u32 subdevice; +}; + +struct flash_file_hdr { + u8 sign[32]; + u32 cksum; + u32 antidote; + struct controller_id cont_id; + u32 file_len; + u32 chunk_num; + u32 total_chunks; + u32 num_imgs; + u8 build[24]; +}; + +struct flash_section_hdr { + u32 format_rev; + u32 cksum; + u32 antidote; + u32 build_no; + u8 id_string[64]; + u32 active_entry_mask; + u32 valid_entry_mask; + u32 org_content_mask; + u32 rsvd0; + u32 rsvd1; + u32 rsvd2; + u32 rsvd3; + u32 rsvd4; +}; + +struct flash_section_entry { + u32 type; + u32 offset; + u32 pad_size; + u32 image_size; + u32 cksum; + u32 entry_point; + u32 rsvd0; + u32 rsvd1; + u8 ver_data[32]; +}; + +struct flash_section_info { + u8 cookie[32]; + struct flash_section_hdr fsec_hdr; + struct flash_section_entry fsec_entry[32]; +}; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 308eb09ca56..409cf059590 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -16,6 +16,7 @@ */ #include "be.h" +#include "be_cmds.h" #include <asm/div64.h> MODULE_VERSION(DRV_VER); @@ -60,40 +61,39 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, return 0; } -static void be_intr_set(struct be_ctrl_info *ctrl, bool enable) +static void be_intr_set(struct be_adapter *adapter, bool enable) { - u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; + u8 __iomem *addr = adapter->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; u32 reg = ioread32(addr); u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; - if (!enabled && enable) { + + if (!enabled && enable) reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; - } else if (enabled && !enable) { + else if (enabled && !enable) reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; - } else { - printk(KERN_WARNING DRV_NAME - ": bad value in membar_int_ctrl reg=0x%x\n", reg); + else return; - } + iowrite32(reg, addr); } -static void be_rxq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted) +static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted) { u32 val = 0; val |= qid & DB_RQ_RING_ID_MASK; val |= posted << DB_RQ_NUM_POSTED_SHIFT; - iowrite32(val, ctrl->db + DB_RQ_OFFSET); + iowrite32(val, adapter->db + DB_RQ_OFFSET); } -static void be_txq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted) +static void be_txq_notify(struct be_adapter *adapter, u16 qid, u16 posted) { u32 val = 0; val |= qid & DB_TXULP_RING_ID_MASK; val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT; - iowrite32(val, ctrl->db + DB_TXULP1_OFFSET); + iowrite32(val, adapter->db + DB_TXULP1_OFFSET); } -static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid, +static void be_eq_notify(struct be_adapter *adapter, u16 qid, bool arm, bool clear_int, u16 num_popped) { u32 val = 0; @@ -104,44 +104,38 @@ static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid, val |= 1 << DB_EQ_CLR_SHIFT; val |= 1 << DB_EQ_EVNT_SHIFT; val |= num_popped << DB_EQ_NUM_POPPED_SHIFT; - iowrite32(val, ctrl->db + DB_EQ_OFFSET); + iowrite32(val, adapter->db + DB_EQ_OFFSET); } -void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, - bool arm, u16 num_popped) +void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) { u32 val = 0; val |= qid & DB_CQ_RING_ID_MASK; if (arm) val |= 1 << DB_CQ_REARM_SHIFT; val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; - iowrite32(val, ctrl->db + DB_CQ_OFFSET); + iowrite32(val, adapter->db + DB_CQ_OFFSET); } - static int be_mac_addr_set(struct net_device *netdev, void *p) { struct be_adapter *adapter = netdev_priv(netdev); struct sockaddr *addr = p; int status = 0; - if (netif_running(netdev)) { - status = be_cmd_pmac_del(&adapter->ctrl, adapter->if_handle, - adapter->pmac_id); - if (status) - return status; - - status = be_cmd_pmac_add(&adapter->ctrl, (u8 *)addr->sa_data, - adapter->if_handle, &adapter->pmac_id); - } + status = be_cmd_pmac_del(adapter, adapter->if_handle, adapter->pmac_id); + if (status) + return status; + status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, + adapter->if_handle, &adapter->pmac_id); if (!status) memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); return status; } -static void netdev_stats_update(struct be_adapter *adapter) +void netdev_stats_update(struct be_adapter *adapter) { struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va); struct be_rxf_stats *rxf_stats = &hw_stats->rxf; @@ -214,9 +208,8 @@ static void netdev_stats_update(struct be_adapter *adapter) dev_stats->tx_window_errors = 0; } -void be_link_status_update(void *ctxt, bool link_up) +void be_link_status_update(struct be_adapter *adapter, bool link_up) { - struct be_adapter *adapter = ctxt; struct net_device *netdev = adapter->netdev; /* If link came up or went down */ @@ -237,7 +230,6 @@ void be_link_status_update(void *ctxt, bool link_up) /* Update the EQ delay n BE based on the RX frags consumed / sec */ static void be_rx_eqd_update(struct be_adapter *adapter) { - struct be_ctrl_info *ctrl = &adapter->ctrl; struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_drvr_stats *stats = &adapter->stats.drvr_stats; ulong now = jiffies; @@ -270,7 +262,7 @@ static void be_rx_eqd_update(struct be_adapter *adapter) if (eqd < 10) eqd = 0; if (eqd != rx_eq->cur_eqd) - be_cmd_modify_eqd(ctrl, rx_eq->q.id, eqd); + be_cmd_modify_eqd(adapter, rx_eq->q.id, eqd); rx_eq->cur_eqd = eqd; } @@ -393,15 +385,19 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_eth_wrb *wrb; struct be_eth_hdr_wrb *hdr; - atomic_add(wrb_cnt, &txq->used); hdr = queue_head_node(txq); + atomic_add(wrb_cnt, &txq->used); queue_head_inc(txq); + if (skb_dma_map(&pdev->dev, skb, DMA_TO_DEVICE)) { + dev_err(&pdev->dev, "TX DMA mapping failed\n"); + return 0; + } + if (skb->len > skb->data_len) { int len = skb->len - skb->data_len; - busaddr = pci_map_single(pdev, skb->data, len, - PCI_DMA_TODEVICE); wrb = queue_head_node(txq); + busaddr = skb_shinfo(skb)->dma_head; wrb_fill(wrb, busaddr, len); be_dws_cpu_to_le(wrb, sizeof(*wrb)); queue_head_inc(txq); @@ -411,9 +407,8 @@ static int make_tx_wrbs(struct be_adapter *adapter, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; - busaddr = pci_map_page(pdev, frag->page, - frag->page_offset, - frag->size, PCI_DMA_TODEVICE); + + busaddr = skb_shinfo(skb)->dma_maps[i]; wrb = queue_head_node(txq); wrb_fill(wrb, busaddr, frag->size); be_dws_cpu_to_le(wrb, sizeof(*wrb)); @@ -435,7 +430,8 @@ static int make_tx_wrbs(struct be_adapter *adapter, return copied; } -static int be_xmit(struct sk_buff *skb, struct net_device *netdev) +static netdev_tx_t be_xmit(struct sk_buff *skb, + struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); struct be_tx_obj *tx_obj = &adapter->tx_obj; @@ -447,23 +443,28 @@ static int be_xmit(struct sk_buff *skb, struct net_device *netdev) wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb); copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb); + if (copied) { + /* record the sent skb in the sent_skb table */ + BUG_ON(tx_obj->sent_skb_list[start]); + tx_obj->sent_skb_list[start] = skb; + + /* Ensure txq has space for the next skb; Else stop the queue + * *BEFORE* ringing the tx doorbell, so that we serialze the + * tx compls of the current transmit which'll wake up the queue + */ + if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= + txq->len) { + netif_stop_queue(netdev); + stopped = true; + } - /* record the sent skb in the sent_skb table */ - BUG_ON(tx_obj->sent_skb_list[start]); - tx_obj->sent_skb_list[start] = skb; + be_txq_notify(adapter, txq->id, wrb_cnt); - /* Ensure that txq has space for the next skb; Else stop the queue - * *BEFORE* ringing the tx doorbell, so that we serialze the - * tx compls of the current transmit which'll wake up the queue - */ - if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= txq->len) { - netif_stop_queue(netdev); - stopped = true; + be_tx_stats_update(adapter, wrb_cnt, copied, stopped); + } else { + txq->head = start; + dev_kfree_skb_any(skb); } - - be_txq_notify(&adapter->ctrl, txq->id, wrb_cnt); - - be_tx_stats_update(adapter, wrb_cnt, copied, stopped); return NETDEV_TX_OK; } @@ -488,11 +489,11 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, * set the BE in promiscuous VLAN mode. */ -static void be_vid_config(struct net_device *netdev) +static int be_vid_config(struct be_adapter *adapter) { - struct be_adapter *adapter = netdev_priv(netdev); u16 vtag[BE_NUM_VLANS_SUPPORTED]; u16 ntags = 0, i; + int status; if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED) { /* Construct VLAN Table to give to HW */ @@ -502,12 +503,13 @@ static void be_vid_config(struct net_device *netdev) ntags++; } } - be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle, - vtag, ntags, 1, 0); + status = be_cmd_vlan_config(adapter, adapter->if_handle, + vtag, ntags, 1, 0); } else { - be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle, - NULL, 0, 1, 1); + status = be_cmd_vlan_config(adapter, adapter->if_handle, + NULL, 0, 1, 1); } + return status; } static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp) @@ -515,13 +517,12 @@ static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp) struct be_adapter *adapter = netdev_priv(netdev); struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq; - struct be_ctrl_info *ctrl = &adapter->ctrl; - be_eq_notify(ctrl, rx_eq->q.id, false, false, 0); - be_eq_notify(ctrl, tx_eq->q.id, false, false, 0); + be_eq_notify(adapter, rx_eq->q.id, false, false, 0); + be_eq_notify(adapter, tx_eq->q.id, false, false, 0); adapter->vlan_grp = grp; - be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); - be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); + be_eq_notify(adapter, rx_eq->q.id, true, false, 0); + be_eq_notify(adapter, tx_eq->q.id, true, false, 0); } static void be_vlan_add_vid(struct net_device *netdev, u16 vid) @@ -531,7 +532,7 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid) adapter->num_vlans++; adapter->vlan_tag[vid] = 1; - be_vid_config(netdev); + be_vid_config(adapter); } static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) @@ -542,16 +543,15 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) adapter->vlan_tag[vid] = 0; vlan_group_set_device(adapter->vlan_grp, vid, NULL); - be_vid_config(netdev); + be_vid_config(adapter); } static void be_set_multicast_list(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_ctrl_info *ctrl = &adapter->ctrl; if (netdev->flags & IFF_PROMISC) { - be_cmd_promiscuous_config(ctrl, adapter->port_num, 1); + be_cmd_promiscuous_config(adapter, adapter->port_num, 1); adapter->promiscuous = true; goto done; } @@ -559,15 +559,15 @@ static void be_set_multicast_list(struct net_device *netdev) /* BE was previously in promiscous mode; disable it */ if (adapter->promiscuous) { adapter->promiscuous = false; - be_cmd_promiscuous_config(ctrl, adapter->port_num, 0); + be_cmd_promiscuous_config(adapter, adapter->port_num, 0); } if (netdev->flags & IFF_ALLMULTI) { - be_cmd_multicast_set(ctrl, adapter->if_handle, NULL, 0); + be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0); goto done; } - be_cmd_multicast_set(ctrl, adapter->if_handle, netdev->mc_list, + be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list, netdev->mc_count); done: return; @@ -667,7 +667,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_queue_info *rxq = &adapter->rx_obj.q; struct be_rx_page_info *page_info; u16 rxq_idx, i, num_rcvd, j; - u32 pktsize, hdr_len, curr_frag_len; + u32 pktsize, hdr_len, curr_frag_len, size; u8 *start; rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); @@ -708,12 +708,13 @@ static void skb_fill_rx_data(struct be_adapter *adapter, } /* More frags present for this completion */ - pktsize -= curr_frag_len; /* account for above copied frag */ + size = pktsize; for (i = 1, j = 0; i < num_rcvd; i++) { + size -= curr_frag_len; index_inc(&rxq_idx, rxq->len); page_info = get_rx_page_info(adapter, rxq_idx); - curr_frag_len = min(pktsize, rx_frag_size); + curr_frag_len = min(size, rx_frag_size); /* Coalesce all frags from the same physical page in one slot */ if (page_info->page_offset == 0) { @@ -731,7 +732,6 @@ static void skb_fill_rx_data(struct be_adapter *adapter, skb_shinfo(skb)->frags[j].size += curr_frag_len; skb->len += curr_frag_len; skb->data_len += curr_frag_len; - pktsize -= curr_frag_len; memset(page_info, 0, sizeof(*page_info)); } @@ -742,7 +742,7 @@ done: return; } -/* Process the RX completion indicated by rxcp when LRO is disabled */ +/* Process the RX completion indicated by rxcp when GRO is disabled */ static void be_rx_compl_process(struct be_adapter *adapter, struct be_eth_rx_compl *rxcp) { @@ -784,18 +784,17 @@ static void be_rx_compl_process(struct be_adapter *adapter, netif_receive_skb(skb); } - adapter->netdev->last_rx = jiffies; - return; } -/* Process the RX completion indicated by rxcp when LRO is enabled */ -static void be_rx_compl_process_lro(struct be_adapter *adapter, +/* Process the RX completion indicated by rxcp when GRO is enabled */ +static void be_rx_compl_process_gro(struct be_adapter *adapter, struct be_eth_rx_compl *rxcp) { struct be_rx_page_info *page_info; - struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; + struct sk_buff *skb = NULL; struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_eq_obj *eq_obj = &adapter->rx_eq; u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; u16 i, rxq_idx = 0, vid, j; @@ -804,6 +803,12 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + skb = napi_get_frags(&eq_obj->napi); + if (!skb) { + be_rx_compl_discard(adapter, rxcp); + return; + } + remaining = pkt_size; for (i = 0, j = -1; i < num_rcvd; i++) { page_info = get_rx_page_info(adapter, rxq_idx); @@ -814,13 +819,14 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, if (i == 0 || page_info->page_offset == 0) { /* First frag or Fresh page */ j++; - rx_frags[j].page = page_info->page; - rx_frags[j].page_offset = page_info->page_offset; - rx_frags[j].size = 0; + skb_shinfo(skb)->frags[j].page = page_info->page; + skb_shinfo(skb)->frags[j].page_offset = + page_info->page_offset; + skb_shinfo(skb)->frags[j].size = 0; } else { put_page(page_info->page); } - rx_frags[j].size += curr_frag_len; + skb_shinfo(skb)->frags[j].size += curr_frag_len; remaining -= curr_frag_len; index_inc(&rxq_idx, rxq->len); @@ -828,9 +834,14 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, } BUG_ON(j > MAX_SKB_FRAGS); + skb_shinfo(skb)->nr_frags = j + 1; + skb->len = pkt_size; + skb->data_len = pkt_size; + skb->truesize += pkt_size; + skb->ip_summed = CHECKSUM_UNNECESSARY; + if (likely(!vlanf)) { - lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size, - pkt_size, NULL, 0); + napi_gro_frags(&eq_obj->napi); } else { vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); vid = be16_to_cpu(vid); @@ -838,9 +849,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter, if (!adapter->vlan_grp || adapter->num_vlans == 0) return; - lro_vlan_hwaccel_receive_frags(&adapter->rx_obj.lro_mgr, - rx_frags, pkt_size, pkt_size, adapter->vlan_grp, - vid, NULL, 0); + vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); } be_rx_stats_update(adapter, pkt_size, num_rcvd); @@ -931,7 +940,7 @@ static void be_post_rx_frags(struct be_adapter *adapter) if (posted) { atomic_add(posted, &rxq->used); - be_rxq_notify(&adapter->ctrl, rxq->id, posted); + be_rxq_notify(adapter, rxq->id, posted); } else if (atomic_read(&rxq->used) == 0) { /* Let be_worker replenish when memory is available */ adapter->rx_post_starved = true; @@ -958,10 +967,8 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq) static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index) { struct be_queue_info *txq = &adapter->tx_obj.q; - struct be_eth_wrb *wrb; struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; struct sk_buff *sent_skb; - u64 busaddr; u16 cur_index, num_wrbs = 0; cur_index = txq->tail; @@ -971,22 +978,65 @@ static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index) do { cur_index = txq->tail; - wrb = queue_tail_node(txq); - be_dws_le_to_cpu(wrb, sizeof(*wrb)); - busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo; - if (busaddr != 0) { - pci_unmap_single(adapter->pdev, busaddr, - wrb->frag_len, PCI_DMA_TODEVICE); - } num_wrbs++; queue_tail_inc(txq); } while (cur_index != last_index); atomic_sub(num_wrbs, &txq->used); - + skb_dma_unmap(&adapter->pdev->dev, sent_skb, DMA_TO_DEVICE); kfree_skb(sent_skb); } +static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj) +{ + struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q); + + if (!eqe->evt) + return NULL; + + eqe->evt = le32_to_cpu(eqe->evt); + queue_tail_inc(&eq_obj->q); + return eqe; +} + +static int event_handle(struct be_adapter *adapter, + struct be_eq_obj *eq_obj) +{ + struct be_eq_entry *eqe; + u16 num = 0; + + while ((eqe = event_get(eq_obj)) != NULL) { + eqe->evt = 0; + num++; + } + + /* Deal with any spurious interrupts that come + * without events + */ + be_eq_notify(adapter, eq_obj->q.id, true, true, num); + if (num) + napi_schedule(&eq_obj->napi); + + return num; +} + +/* Just read and notify events without processing them. + * Used at the time of destroying event queues */ +static void be_eq_clean(struct be_adapter *adapter, + struct be_eq_obj *eq_obj) +{ + struct be_eq_entry *eqe; + u16 num = 0; + + while ((eqe = event_get(eq_obj)) != NULL) { + eqe->evt = 0; + num++; + } + + if (num) + be_eq_notify(adapter, eq_obj->q.id, false, true, num); +} + static void be_rx_q_clean(struct be_adapter *adapter) { struct be_rx_page_info *page_info; @@ -999,12 +1049,12 @@ static void be_rx_q_clean(struct be_adapter *adapter) while ((rxcp = be_rx_compl_get(adapter)) != NULL) { be_rx_compl_discard(adapter, rxcp); be_rx_compl_reset(rxcp); - be_cq_notify(&adapter->ctrl, rx_cq->id, true, 1); + be_cq_notify(adapter, rx_cq->id, true, 1); } /* Then free posted rx buffer that were not used */ tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; - for (; tail != rxq->head; index_inc(&tail, rxq->len)) { + for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) { page_info = get_rx_page_info(adapter, tail); put_page(page_info->page); memset(page_info, 0, sizeof(*page_info)); @@ -1012,36 +1062,49 @@ static void be_rx_q_clean(struct be_adapter *adapter) BUG_ON(atomic_read(&rxq->used)); } -static void be_tx_q_clean(struct be_adapter *adapter) +static void be_tx_compl_clean(struct be_adapter *adapter) { - struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; - struct sk_buff *sent_skb; + struct be_queue_info *tx_cq = &adapter->tx_obj.cq; struct be_queue_info *txq = &adapter->tx_obj.q; - u16 last_index; - bool dummy_wrb; - - while (atomic_read(&txq->used)) { - sent_skb = sent_skbs[txq->tail]; - last_index = txq->tail; - index_adv(&last_index, - wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len); - be_tx_compl_process(adapter, last_index); - } + struct be_eth_tx_compl *txcp; + u16 end_idx, cmpl = 0, timeo = 0; + + /* Wait for a max of 200ms for all the tx-completions to arrive. */ + do { + while ((txcp = be_tx_compl_get(tx_cq))) { + end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, + wrb_index, txcp); + be_tx_compl_process(adapter, end_idx); + cmpl++; + } + if (cmpl) { + be_cq_notify(adapter, tx_cq->id, false, cmpl); + cmpl = 0; + } + + if (atomic_read(&txq->used) == 0 || ++timeo > 200) + break; + + mdelay(1); + } while (true); + + if (atomic_read(&txq->used)) + dev_err(&adapter->pdev->dev, "%d pending tx-completions\n", + atomic_read(&txq->used)); } static void be_mcc_queues_destroy(struct be_adapter *adapter) { struct be_queue_info *q; - struct be_ctrl_info *ctrl = &adapter->ctrl; - q = &ctrl->mcc_obj.q; + q = &adapter->mcc_obj.q; if (q->created) - be_cmd_q_destroy(ctrl, q, QTYPE_MCCQ); + be_cmd_q_destroy(adapter, q, QTYPE_MCCQ); be_queue_free(adapter, q); - q = &ctrl->mcc_obj.cq; + q = &adapter->mcc_obj.cq; if (q->created) - be_cmd_q_destroy(ctrl, q, QTYPE_CQ); + be_cmd_q_destroy(adapter, q, QTYPE_CQ); be_queue_free(adapter, q); } @@ -1049,25 +1112,24 @@ static void be_mcc_queues_destroy(struct be_adapter *adapter) static int be_mcc_queues_create(struct be_adapter *adapter) { struct be_queue_info *q, *cq; - struct be_ctrl_info *ctrl = &adapter->ctrl; /* Alloc MCC compl queue */ - cq = &ctrl->mcc_obj.cq; + cq = &adapter->mcc_obj.cq; if (be_queue_alloc(adapter, cq, MCC_CQ_LEN, - sizeof(struct be_mcc_cq_entry))) + sizeof(struct be_mcc_compl))) goto err; /* Ask BE to create MCC compl queue; share TX's eq */ - if (be_cmd_cq_create(ctrl, cq, &adapter->tx_eq.q, false, true, 0)) + if (be_cmd_cq_create(adapter, cq, &adapter->tx_eq.q, false, true, 0)) goto mcc_cq_free; /* Alloc MCC queue */ - q = &ctrl->mcc_obj.q; + q = &adapter->mcc_obj.q; if (be_queue_alloc(adapter, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb))) goto mcc_cq_destroy; /* Ask BE to create MCC queue */ - if (be_cmd_mccq_create(ctrl, q, cq)) + if (be_cmd_mccq_create(adapter, q, cq)) goto mcc_q_free; return 0; @@ -1075,7 +1137,7 @@ static int be_mcc_queues_create(struct be_adapter *adapter) mcc_q_free: be_queue_free(adapter, q); mcc_cq_destroy: - be_cmd_q_destroy(ctrl, cq, QTYPE_CQ); + be_cmd_q_destroy(adapter, cq, QTYPE_CQ); mcc_cq_free: be_queue_free(adapter, cq); err: @@ -1087,23 +1149,21 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) struct be_queue_info *q; q = &adapter->tx_obj.q; - if (q->created) { - be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_TXQ); - - /* No more tx completions can be rcvd now; clean up if there - * are any pending completions or pending tx requests */ - be_tx_q_clean(adapter); - } + if (q->created) + be_cmd_q_destroy(adapter, q, QTYPE_TXQ); be_queue_free(adapter, q); q = &adapter->tx_obj.cq; if (q->created) - be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ); + be_cmd_q_destroy(adapter, q, QTYPE_CQ); be_queue_free(adapter, q); + /* Clear any residual events */ + be_eq_clean(adapter, &adapter->tx_eq); + q = &adapter->tx_eq.q; if (q->created) - be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ); + be_cmd_q_destroy(adapter, q, QTYPE_EQ); be_queue_free(adapter, q); } @@ -1121,7 +1181,7 @@ static int be_tx_queues_create(struct be_adapter *adapter) return -1; /* Ask BE to create Tx Event queue */ - if (be_cmd_eq_create(&adapter->ctrl, eq, adapter->tx_eq.cur_eqd)) + if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd)) goto tx_eq_free; /* Alloc TX eth compl queue */ cq = &adapter->tx_obj.cq; @@ -1130,7 +1190,7 @@ static int be_tx_queues_create(struct be_adapter *adapter) goto tx_eq_destroy; /* Ask BE to create Tx eth compl queue */ - if (be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3)) + if (be_cmd_cq_create(adapter, cq, eq, false, false, 3)) goto tx_cq_free; /* Alloc TX eth queue */ @@ -1139,18 +1199,18 @@ static int be_tx_queues_create(struct be_adapter *adapter) goto tx_cq_destroy; /* Ask BE to create Tx eth queue */ - if (be_cmd_txq_create(&adapter->ctrl, q, cq)) + if (be_cmd_txq_create(adapter, q, cq)) goto tx_q_free; return 0; tx_q_free: be_queue_free(adapter, q); tx_cq_destroy: - be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ); + be_cmd_q_destroy(adapter, cq, QTYPE_CQ); tx_cq_free: be_queue_free(adapter, cq); tx_eq_destroy: - be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ); + be_cmd_q_destroy(adapter, eq, QTYPE_EQ); tx_eq_free: be_queue_free(adapter, eq); return -1; @@ -1162,19 +1222,22 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) q = &adapter->rx_obj.q; if (q->created) { - be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_RXQ); + be_cmd_q_destroy(adapter, q, QTYPE_RXQ); be_rx_q_clean(adapter); } be_queue_free(adapter, q); q = &adapter->rx_obj.cq; if (q->created) - be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ); + be_cmd_q_destroy(adapter, q, QTYPE_CQ); be_queue_free(adapter, q); + /* Clear any residual events */ + be_eq_clean(adapter, &adapter->rx_eq); + q = &adapter->rx_eq.q; if (q->created) - be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ); + be_cmd_q_destroy(adapter, q, QTYPE_EQ); be_queue_free(adapter, q); } @@ -1183,7 +1246,6 @@ static int be_rx_queues_create(struct be_adapter *adapter) struct be_queue_info *eq, *q, *cq; int rc; - adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME; adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; adapter->rx_eq.max_eqd = BE_MAX_EQD; adapter->rx_eq.min_eqd = 0; @@ -1198,7 +1260,7 @@ static int be_rx_queues_create(struct be_adapter *adapter) return rc; /* Ask BE to create Rx Event queue */ - rc = be_cmd_eq_create(&adapter->ctrl, eq, adapter->rx_eq.cur_eqd); + rc = be_cmd_eq_create(adapter, eq, adapter->rx_eq.cur_eqd); if (rc) goto rx_eq_free; @@ -1210,7 +1272,7 @@ static int be_rx_queues_create(struct be_adapter *adapter) goto rx_eq_destroy; /* Ask BE to create Rx eth compl queue */ - rc = be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3); + rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3); if (rc) goto rx_cq_free; @@ -1221,7 +1283,7 @@ static int be_rx_queues_create(struct be_adapter *adapter) goto rx_cq_destroy; /* Ask BE to create Rx eth queue */ - rc = be_cmd_rxq_create(&adapter->ctrl, q, cq->id, rx_frag_size, + rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, false); if (rc) goto rx_q_free; @@ -1230,66 +1292,43 @@ static int be_rx_queues_create(struct be_adapter *adapter) rx_q_free: be_queue_free(adapter, q); rx_cq_destroy: - be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ); + be_cmd_q_destroy(adapter, cq, QTYPE_CQ); rx_cq_free: be_queue_free(adapter, cq); rx_eq_destroy: - be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ); + be_cmd_q_destroy(adapter, eq, QTYPE_EQ); rx_eq_free: be_queue_free(adapter, eq); return rc; } -static bool event_get(struct be_eq_obj *eq_obj, u16 *rid) -{ - struct be_eq_entry *entry = queue_tail_node(&eq_obj->q); - u32 evt = entry->evt; - - if (!evt) - return false; - - evt = le32_to_cpu(evt); - *rid = (evt >> EQ_ENTRY_RES_ID_SHIFT) & EQ_ENTRY_RES_ID_MASK; - entry->evt = 0; - queue_tail_inc(&eq_obj->q); - return true; -} -static int event_handle(struct be_ctrl_info *ctrl, - struct be_eq_obj *eq_obj) +/* There are 8 evt ids per func. Retruns the evt id's bit number */ +static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id) { - u16 rid = 0, num = 0; - - while (event_get(eq_obj, &rid)) - num++; - - /* We can see an interrupt and no event */ - be_eq_notify(ctrl, eq_obj->q.id, true, true, num); - if (num) - napi_schedule(&eq_obj->napi); - - return num; + return eq_id - 8 * be_pci_func(adapter); } static irqreturn_t be_intx(int irq, void *dev) { struct be_adapter *adapter = dev; - struct be_ctrl_info *ctrl = &adapter->ctrl; - int rx, tx; - - tx = event_handle(ctrl, &adapter->tx_eq); - rx = event_handle(ctrl, &adapter->rx_eq); + int isr; - if (rx || tx) - return IRQ_HANDLED; - else + isr = ioread32(adapter->csr + CEV_ISR0_OFFSET + + be_pci_func(adapter) * CEV_ISR_SIZE); + if (!isr) return IRQ_NONE; + + event_handle(adapter, &adapter->tx_eq); + event_handle(adapter, &adapter->rx_eq); + + return IRQ_HANDLED; } static irqreturn_t be_msix_rx(int irq, void *dev) { struct be_adapter *adapter = dev; - event_handle(&adapter->ctrl, &adapter->rx_eq); + event_handle(adapter, &adapter->rx_eq); return IRQ_HANDLED; } @@ -1298,12 +1337,12 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev) { struct be_adapter *adapter = dev; - event_handle(&adapter->ctrl, &adapter->tx_eq); + event_handle(adapter, &adapter->tx_eq); return IRQ_HANDLED; } -static inline bool do_lro(struct be_adapter *adapter, +static inline bool do_gro(struct be_adapter *adapter, struct be_eth_rx_compl *rxcp) { int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp); @@ -1312,8 +1351,7 @@ static inline bool do_lro(struct be_adapter *adapter, if (err) drvr_stats(adapter)->be_rxcp_err++; - return (!tcp_frame || err || (adapter->max_rx_coal <= 1)) ? - false : true; + return (tcp_frame && !err) ? true : false; } int be_poll_rx(struct napi_struct *napi, int budget) @@ -1330,16 +1368,14 @@ int be_poll_rx(struct napi_struct *napi, int budget) if (!rxcp) break; - if (do_lro(adapter, rxcp)) - be_rx_compl_process_lro(adapter, rxcp); + if (do_gro(adapter, rxcp)) + be_rx_compl_process_gro(adapter, rxcp); else be_rx_compl_process(adapter, rxcp); be_rx_compl_reset(rxcp); } - lro_flush_all(&adapter->rx_obj.lro_mgr); - /* Refill the queue */ if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM) be_post_rx_frags(adapter); @@ -1347,10 +1383,10 @@ int be_poll_rx(struct napi_struct *napi, int budget) /* All consumed */ if (work_done < budget) { napi_complete(napi); - be_cq_notify(&adapter->ctrl, rx_cq->id, true, work_done); + be_cq_notify(adapter, rx_cq->id, true, work_done); } else { /* More to be consumed; continue with interrupts disabled */ - be_cq_notify(&adapter->ctrl, rx_cq->id, false, work_done); + be_cq_notify(adapter, rx_cq->id, false, work_done); } return work_done; } @@ -1371,7 +1407,7 @@ void be_process_tx(struct be_adapter *adapter) } if (num_cmpl) { - be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl); + be_cq_notify(adapter, tx_cq->id, true, num_cmpl); /* As Tx wrbs have been freed up, wake up netdev queue if * it was stopped due to lack of tx wrbs. @@ -1399,7 +1435,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) be_process_tx(adapter); - be_process_mcc(&adapter->ctrl); + be_process_mcc(adapter); return 1; } @@ -1408,12 +1444,8 @@ static void be_worker(struct work_struct *work) { struct be_adapter *adapter = container_of(work, struct be_adapter, work.work); - int status; - /* Get Stats */ - status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); - if (!status) - netdev_stats_update(adapter); + be_cmd_get_stats(adapter, &adapter->stats.cmd); /* Set EQ delay */ be_rx_eqd_update(adapter); @@ -1445,32 +1477,44 @@ static void be_msix_enable(struct be_adapter *adapter) static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id) { - return adapter->msix_entries[eq_id - - 8 * adapter->ctrl.pci_func].vector; + return adapter->msix_entries[ + be_evt_bit_get(adapter, eq_id)].vector; } -static int be_msix_register(struct be_adapter *adapter) +static int be_request_irq(struct be_adapter *adapter, + struct be_eq_obj *eq_obj, + void *handler, char *desc) { struct net_device *netdev = adapter->netdev; - struct be_eq_obj *tx_eq = &adapter->tx_eq; - struct be_eq_obj *rx_eq = &adapter->rx_eq; - int status, vec; + int vec; + + sprintf(eq_obj->desc, "%s-%s", netdev->name, desc); + vec = be_msix_vec_get(adapter, eq_obj->q.id); + return request_irq(vec, handler, 0, eq_obj->desc, adapter); +} + +static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj) +{ + int vec = be_msix_vec_get(adapter, eq_obj->q.id); + free_irq(vec, adapter); +} + +static int be_msix_register(struct be_adapter *adapter) +{ + int status; - sprintf(tx_eq->desc, "%s-tx", netdev->name); - vec = be_msix_vec_get(adapter, tx_eq->q.id); - status = request_irq(vec, be_msix_tx_mcc, 0, tx_eq->desc, adapter); + status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx"); if (status) goto err; - sprintf(rx_eq->desc, "%s-rx", netdev->name); - vec = be_msix_vec_get(adapter, rx_eq->q.id); - status = request_irq(vec, be_msix_rx, 0, rx_eq->desc, adapter); - if (status) { /* Free TX IRQ */ - vec = be_msix_vec_get(adapter, tx_eq->q.id); - free_irq(vec, adapter); - goto err; - } + status = be_request_irq(adapter, &adapter->rx_eq, be_msix_rx, "rx"); + if (status) + goto free_tx_irq; + return 0; + +free_tx_irq: + be_free_irq(adapter, &adapter->tx_eq); err: dev_warn(&adapter->pdev->dev, "MSIX Request IRQ failed - err %d\n", status); @@ -1507,7 +1551,6 @@ done: static void be_irq_unregister(struct be_adapter *adapter) { struct net_device *netdev = adapter->netdev; - int vec; if (!adapter->isr_registered) return; @@ -1519,10 +1562,8 @@ static void be_irq_unregister(struct be_adapter *adapter) } /* MSIx */ - vec = be_msix_vec_get(adapter, adapter->tx_eq.q.id); - free_irq(vec, adapter); - vec = be_msix_vec_get(adapter, adapter->rx_eq.q.id); - free_irq(vec, adapter); + be_free_irq(adapter, &adapter->tx_eq); + be_free_irq(adapter, &adapter->rx_eq); done: adapter->isr_registered = false; return; @@ -1531,7 +1572,6 @@ done: static int be_open(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_ctrl_info *ctrl = &adapter->ctrl; struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq; bool link_up; @@ -1545,16 +1585,16 @@ static int be_open(struct net_device *netdev) be_irq_register(adapter); - be_intr_set(ctrl, true); + be_intr_set(adapter, true); /* The evt queues are created in unarmed state; arm them */ - be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); - be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); + be_eq_notify(adapter, rx_eq->q.id, true, false, 0); + be_eq_notify(adapter, tx_eq->q.id, true, false, 0); /* Rx compl queue may be in unarmed state; rearm it */ - be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0); + be_cq_notify(adapter, adapter->rx_obj.cq.id, true, 0); - status = be_cmd_link_status_query(ctrl, &link_up); + status = be_cmd_link_status_query(adapter, &link_up); if (status) return status; be_link_status_update(adapter, link_up); @@ -1565,7 +1605,6 @@ static int be_open(struct net_device *netdev) static int be_setup(struct be_adapter *adapter) { - struct be_ctrl_info *ctrl = &adapter->ctrl; struct net_device *netdev = adapter->netdev; u32 if_flags; int status; @@ -1573,17 +1612,12 @@ static int be_setup(struct be_adapter *adapter) if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS | BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_PASS_L3L4_ERRORS; - status = be_cmd_if_create(ctrl, if_flags, netdev->dev_addr, + status = be_cmd_if_create(adapter, if_flags, netdev->dev_addr, false/* pmac_invalid */, &adapter->if_handle, &adapter->pmac_id); if (status != 0) goto do_none; - be_vid_config(netdev); - - status = be_cmd_set_flow_control(ctrl, true, true); - if (status != 0) - goto if_destroy; status = be_tx_queues_create(adapter); if (status != 0) @@ -1597,35 +1631,41 @@ static int be_setup(struct be_adapter *adapter) if (status != 0) goto rx_qs_destroy; + status = be_vid_config(adapter); + if (status != 0) + goto mccqs_destroy; + + status = be_cmd_set_flow_control(adapter, true, true); + if (status != 0) + goto mccqs_destroy; return 0; +mccqs_destroy: + be_mcc_queues_destroy(adapter); rx_qs_destroy: be_rx_queues_destroy(adapter); tx_qs_destroy: be_tx_queues_destroy(adapter); if_destroy: - be_cmd_if_destroy(ctrl, adapter->if_handle); + be_cmd_if_destroy(adapter, adapter->if_handle); do_none: return status; } static int be_clear(struct be_adapter *adapter) { - struct be_ctrl_info *ctrl = &adapter->ctrl; - + be_mcc_queues_destroy(adapter); be_rx_queues_destroy(adapter); be_tx_queues_destroy(adapter); - be_cmd_if_destroy(ctrl, adapter->if_handle); + be_cmd_if_destroy(adapter, adapter->if_handle); - be_mcc_queues_destroy(adapter); return 0; } static int be_close(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_ctrl_info *ctrl = &adapter->ctrl; struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq; int vec; @@ -1636,7 +1676,7 @@ static int be_close(struct net_device *netdev) netif_carrier_off(netdev); adapter->link_up = false; - be_intr_set(ctrl, false); + be_intr_set(adapter, false); if (adapter->msix_enabled) { vec = be_msix_vec_get(adapter, tx_eq->q.id); @@ -1651,58 +1691,179 @@ static int be_close(struct net_device *netdev) napi_disable(&rx_eq->napi); napi_disable(&tx_eq->napi); + /* Wait for all pending tx completions to arrive so that + * all tx skbs are freed. + */ + be_tx_compl_clean(adapter); + return 0; } -static int be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, - u64 *hdr_flags, void *priv) +#define FW_FILE_HDR_SIGN "ServerEngines Corp. " +char flash_cookie[2][16] = {"*** SE FLAS", + "H DIRECTORY *** "}; +static int be_flash_image(struct be_adapter *adapter, + const struct firmware *fw, + struct be_dma_mem *flash_cmd, u32 flash_type) { - struct ethhdr *eh; - struct vlan_ethhdr *veh; - struct iphdr *iph; - u8 *va = page_address(frag->page) + frag->page_offset; - unsigned long ll_hlen; + int status; + u32 flash_op, image_offset = 0, total_bytes, image_size = 0; + int num_bytes; + const u8 *p = fw->data; + struct be_cmd_write_flashrom *req = flash_cmd->va; + + switch (flash_type) { + case FLASHROM_TYPE_ISCSI_ACTIVE: + image_offset = FLASH_iSCSI_PRIMARY_IMAGE_START; + image_size = FLASH_IMAGE_MAX_SIZE; + break; + case FLASHROM_TYPE_ISCSI_BACKUP: + image_offset = FLASH_iSCSI_BACKUP_IMAGE_START; + image_size = FLASH_IMAGE_MAX_SIZE; + break; + case FLASHROM_TYPE_FCOE_FW_ACTIVE: + image_offset = FLASH_FCoE_PRIMARY_IMAGE_START; + image_size = FLASH_IMAGE_MAX_SIZE; + break; + case FLASHROM_TYPE_FCOE_FW_BACKUP: + image_offset = FLASH_FCoE_BACKUP_IMAGE_START; + image_size = FLASH_IMAGE_MAX_SIZE; + break; + case FLASHROM_TYPE_BIOS: + image_offset = FLASH_iSCSI_BIOS_START; + image_size = FLASH_BIOS_IMAGE_MAX_SIZE; + break; + case FLASHROM_TYPE_FCOE_BIOS: + image_offset = FLASH_FCoE_BIOS_START; + image_size = FLASH_BIOS_IMAGE_MAX_SIZE; + break; + case FLASHROM_TYPE_PXE_BIOS: + image_offset = FLASH_PXE_BIOS_START; + image_size = FLASH_BIOS_IMAGE_MAX_SIZE; + break; + default: + return 0; + } + + p += sizeof(struct flash_file_hdr) + image_offset; + if (p + image_size > fw->data + fw->size) + return -1; - prefetch(va); - eh = (struct ethhdr *)va; - *mac_hdr = eh; - ll_hlen = ETH_HLEN; - if (eh->h_proto != htons(ETH_P_IP)) { - if (eh->h_proto == htons(ETH_P_8021Q)) { - veh = (struct vlan_ethhdr *)va; - if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) - return -1; + total_bytes = image_size; - ll_hlen += VLAN_HLEN; - } else { + while (total_bytes) { + if (total_bytes > 32*1024) + num_bytes = 32*1024; + else + num_bytes = total_bytes; + total_bytes -= num_bytes; + + if (!total_bytes) + flash_op = FLASHROM_OPER_FLASH; + else + flash_op = FLASHROM_OPER_SAVE; + memcpy(req->params.data_buf, p, num_bytes); + p += num_bytes; + status = be_cmd_write_flashrom(adapter, flash_cmd, + flash_type, flash_op, num_bytes); + if (status) { + dev_err(&adapter->pdev->dev, + "cmd to write to flash rom failed. type/op %d/%d\n", + flash_type, flash_op); return -1; } + yield(); } - *hdr_flags = LRO_IPV4; - iph = (struct iphdr *)(va + ll_hlen); - *ip_hdr = iph; - if (iph->protocol != IPPROTO_TCP) - return -1; - *hdr_flags |= LRO_TCP; - *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); return 0; } -static void be_lro_init(struct be_adapter *adapter, struct net_device *netdev) +int be_load_fw(struct be_adapter *adapter, u8 *func) { - struct net_lro_mgr *lro_mgr; + char fw_file[ETHTOOL_FLASH_MAX_FILENAME]; + const struct firmware *fw; + struct flash_file_hdr *fhdr; + struct flash_section_info *fsec = NULL; + struct be_dma_mem flash_cmd; + int status; + const u8 *p; + bool entry_found = false; + int flash_type; + char fw_ver[FW_VER_LEN]; + char fw_cfg; + + status = be_cmd_get_fw_ver(adapter, fw_ver); + if (status) + return status; + + fw_cfg = *(fw_ver + 2); + if (fw_cfg == '0') + fw_cfg = '1'; + strcpy(fw_file, func); + + status = request_firmware(&fw, fw_file, &adapter->pdev->dev); + if (status) + goto fw_exit; + + p = fw->data; + fhdr = (struct flash_file_hdr *) p; + if (memcmp(fhdr->sign, FW_FILE_HDR_SIGN, strlen(FW_FILE_HDR_SIGN))) { + dev_err(&adapter->pdev->dev, + "Firmware(%s) load error (signature did not match)\n", + fw_file); + status = -1; + goto fw_exit; + } + + dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); + + p += sizeof(struct flash_file_hdr); + while (p < (fw->data + fw->size)) { + fsec = (struct flash_section_info *)p; + if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) { + entry_found = true; + break; + } + p += 32; + } + + if (!entry_found) { + status = -1; + dev_err(&adapter->pdev->dev, + "Flash cookie not found in firmware image\n"); + goto fw_exit; + } + + flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; + flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size, + &flash_cmd.dma); + if (!flash_cmd.va) { + status = -ENOMEM; + dev_err(&adapter->pdev->dev, + "Memory allocation failure while flashing\n"); + goto fw_exit; + } + + for (flash_type = FLASHROM_TYPE_ISCSI_ACTIVE; + flash_type <= FLASHROM_TYPE_FCOE_FW_BACKUP; flash_type++) { + status = be_flash_image(adapter, fw, &flash_cmd, + flash_type); + if (status) + break; + } + + pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va, + flash_cmd.dma); + if (status) { + dev_err(&adapter->pdev->dev, "Firmware load error\n"); + goto fw_exit; + } - lro_mgr = &adapter->rx_obj.lro_mgr; - lro_mgr->dev = netdev; - lro_mgr->features = LRO_F_NAPI; - lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; - lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; - lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS; - lro_mgr->lro_arr = adapter->rx_obj.lro_desc; - lro_mgr->get_frag_header = be_get_frag_header; - lro_mgr->max_aggr = BE_MAX_FRAGS_PER_FRAME; + dev_info(&adapter->pdev->dev, "Firmware flashed succesfully\n"); + +fw_exit: + release_firmware(fw); + return status; } static struct net_device_ops be_netdev_ops = { @@ -1725,18 +1886,18 @@ static void be_netdev_init(struct net_device *netdev) netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM; + NETIF_F_IPV6_CSUM | NETIF_F_GRO; netdev->flags |= IFF_MULTICAST; adapter->rx_csum = true; + netif_set_gso_max_size(netdev, 65535); + BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); - be_lro_init(adapter, netdev); - netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx, BE_NAPI_WEIGHT); netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc, @@ -1748,13 +1909,12 @@ static void be_netdev_init(struct net_device *netdev) static void be_unmap_pci_bars(struct be_adapter *adapter) { - struct be_ctrl_info *ctrl = &adapter->ctrl; - if (ctrl->csr) - iounmap(ctrl->csr); - if (ctrl->db) - iounmap(ctrl->db); - if (ctrl->pcicfg) - iounmap(ctrl->pcicfg); + if (adapter->csr) + iounmap(adapter->csr); + if (adapter->db) + iounmap(adapter->db); + if (adapter->pcicfg) + iounmap(adapter->pcicfg); } static int be_map_pci_bars(struct be_adapter *adapter) @@ -1765,19 +1925,19 @@ static int be_map_pci_bars(struct be_adapter *adapter) pci_resource_len(adapter->pdev, 2)); if (addr == NULL) return -ENOMEM; - adapter->ctrl.csr = addr; + adapter->csr = addr; addr = ioremap_nocache(pci_resource_start(adapter->pdev, 4), 128 * 1024); if (addr == NULL) goto pci_map_err; - adapter->ctrl.db = addr; + adapter->db = addr; addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1), pci_resource_len(adapter->pdev, 1)); if (addr == NULL) goto pci_map_err; - adapter->ctrl.pcicfg = addr; + adapter->pcicfg = addr; return 0; pci_map_err: @@ -1788,7 +1948,7 @@ pci_map_err: static void be_ctrl_cleanup(struct be_adapter *adapter) { - struct be_dma_mem *mem = &adapter->ctrl.mbox_mem_alloced; + struct be_dma_mem *mem = &adapter->mbox_mem_alloced; be_unmap_pci_bars(adapter); @@ -1797,14 +1957,11 @@ static void be_ctrl_cleanup(struct be_adapter *adapter) mem->va, mem->dma); } -/* Initialize the mbox required to send cmds to BE */ static int be_ctrl_init(struct be_adapter *adapter) { - struct be_ctrl_info *ctrl = &adapter->ctrl; - struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced; - struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem; + struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced; + struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem; int status; - u32 val; status = be_map_pci_bars(adapter); if (status) @@ -1821,16 +1978,10 @@ static int be_ctrl_init(struct be_adapter *adapter) mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); - spin_lock_init(&ctrl->mbox_lock); - spin_lock_init(&ctrl->mcc_lock); - spin_lock_init(&ctrl->mcc_cq_lock); - - ctrl->async_cb = be_link_status_update; - ctrl->adapter_ctxt = adapter; + spin_lock_init(&adapter->mbox_lock); + spin_lock_init(&adapter->mcc_lock); + spin_lock_init(&adapter->mcc_cq_lock); - val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); - ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) & - MEMBAR_CTRL_INT_CTRL_PFUNC_MASK; return 0; } @@ -1884,18 +2035,17 @@ static void __devexit be_remove(struct pci_dev *pdev) static int be_hw_up(struct be_adapter *adapter) { - struct be_ctrl_info *ctrl = &adapter->ctrl; int status; - status = be_cmd_POST(ctrl); + status = be_cmd_POST(adapter); if (status) return status; - status = be_cmd_get_fw_ver(ctrl, adapter->fw_ver); + status = be_cmd_get_fw_ver(adapter, adapter->fw_ver); if (status) return status; - status = be_cmd_query_fw_cfg(ctrl, &adapter->port_num); + status = be_cmd_query_fw_cfg(adapter, &adapter->port_num); return status; } @@ -1905,7 +2055,6 @@ static int __devinit be_probe(struct pci_dev *pdev, int status = 0; struct be_adapter *adapter; struct net_device *netdev; - struct be_ctrl_info *ctrl; u8 mac[ETH_ALEN]; status = pci_enable_device(pdev); @@ -1940,11 +2089,14 @@ static int __devinit be_probe(struct pci_dev *pdev, } } - ctrl = &adapter->ctrl; status = be_ctrl_init(adapter); if (status) goto free_netdev; + status = be_cmd_reset_function(adapter); + if (status) + goto ctrl_clean; + status = be_stats_init(adapter); if (status) goto ctrl_clean; @@ -1953,7 +2105,7 @@ static int __devinit be_probe(struct pci_dev *pdev, if (status) goto stats_clean; - status = be_cmd_mac_addr_query(ctrl, mac, MAC_ADDRESS_TYPE_NETWORK, + status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, true /* permanent */, 0); if (status) goto stats_clean; @@ -1999,9 +2151,9 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) if (netif_running(netdev)) { rtnl_lock(); be_close(netdev); - be_clear(adapter); rtnl_unlock(); } + be_clear(adapter); pci_save_state(pdev); pci_disable_device(pdev); @@ -2024,9 +2176,9 @@ static int be_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_restore_state(pdev); + be_setup(adapter); if (netif_running(netdev)) { rtnl_lock(); - be_setup(adapter); be_open(netdev); rtnl_unlock(); } @@ -2052,12 +2204,6 @@ static int __init be_init_module(void) " Using 2048\n"); rx_frag_size = 2048; } - /* Ensure rx_frag_size is aligned to chache line */ - if (SKB_DATA_ALIGN(rx_frag_size) != rx_frag_size) { - printk(KERN_WARNING DRV_NAME - " : Bad module param rx_frag_size. Using 2048\n"); - rx_frag_size = 2048; - } return pci_register_driver(&be_driver); } |