Commit 5fb379ee authored by Sathya Perla's avatar Sathya Perla Committed by David S. Miller

be2net: Add MCC queue mechanism for BE cmds

Currenlty all cmds use the blocking MCC mbox to post cmds. An mbox cmd is protected
via a spin_lock(cmd_lock) and not spin_lock_bh() as it is undesirable
to disable BHs while a blocking mbox cmd is in progress (and take long to finish.)
This can lockup a cmd in progress in process context. Instead cmds that may be
called in BH context must use the MCC queue to post cmds. The cmd completions
are rcvd in a separate completion queue and the events are placed in the tx-event
queue.
Signed-off-by: default avatarSathya Perla <sathyap@serverengines.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e3453f63
...@@ -65,7 +65,7 @@ static inline char *nic_name(struct pci_dev *pdev) ...@@ -65,7 +65,7 @@ static inline char *nic_name(struct pci_dev *pdev)
#define TX_CQ_LEN 1024 #define TX_CQ_LEN 1024
#define RX_Q_LEN 1024 /* Does not support any other value */ #define RX_Q_LEN 1024 /* Does not support any other value */
#define RX_CQ_LEN 1024 #define RX_CQ_LEN 1024
#define MCC_Q_LEN 64 /* total size not to exceed 8 pages */ #define MCC_Q_LEN 128 /* total size not to exceed 8 pages */
#define MCC_CQ_LEN 256 #define MCC_CQ_LEN 256
#define BE_NAPI_WEIGHT 64 #define BE_NAPI_WEIGHT 64
...@@ -91,6 +91,61 @@ struct be_queue_info { ...@@ -91,6 +91,61 @@ struct be_queue_info {
atomic_t used; /* Number of valid elements in the queue */ atomic_t used; /* Number of valid elements in the queue */
}; };
static inline u32 MODULO(u16 val, u16 limit)
{
BUG_ON(limit & (limit - 1));
return val & (limit - 1);
}
static inline void index_adv(u16 *index, u16 val, u16 limit)
{
*index = MODULO((*index + val), limit);
}
static inline void index_inc(u16 *index, u16 limit)
{
*index = MODULO((*index + 1), limit);
}
static inline void *queue_head_node(struct be_queue_info *q)
{
return q->dma_mem.va + q->head * q->entry_size;
}
static inline void *queue_tail_node(struct be_queue_info *q)
{
return q->dma_mem.va + q->tail * q->entry_size;
}
static inline void queue_head_inc(struct be_queue_info *q)
{
index_inc(&q->head, q->len);
}
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];
/* Adaptive interrupt coalescing (AIC) info */
bool enable_aic;
u16 min_eqd; /* in usecs */
u16 max_eqd; /* in usecs */
u16 cur_eqd; /* in usecs */
struct napi_struct napi;
};
struct be_mcc_obj {
struct be_queue_info q;
struct be_queue_info cq;
};
struct be_ctrl_info { struct be_ctrl_info {
u8 __iomem *csr; u8 __iomem *csr;
u8 __iomem *db; /* Door Bell */ u8 __iomem *db; /* Door Bell */
...@@ -98,11 +153,16 @@ struct be_ctrl_info { ...@@ -98,11 +153,16 @@ struct be_ctrl_info {
int pci_func; int pci_func;
/* Mbox used for cmd request/response */ /* Mbox used for cmd request/response */
spinlock_t cmd_lock; /* For serializing cmds to BE card */ spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */
struct be_dma_mem mbox_mem; struct be_dma_mem mbox_mem;
/* Mbox mem is adjusted to align to 16 bytes. The allocated addr /* Mbox mem is adjusted to align to 16 bytes. The allocated addr
* is stored for freeing purpose */ * is stored for freeing purpose */
struct be_dma_mem mbox_mem_alloced; 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;
}; };
#include "be_cmds.h" #include "be_cmds.h"
...@@ -150,19 +210,6 @@ struct be_stats_obj { ...@@ -150,19 +210,6 @@ struct be_stats_obj {
struct be_dma_mem cmd; struct be_dma_mem cmd;
}; };
struct be_eq_obj {
struct be_queue_info q;
char desc[32];
/* Adaptive interrupt coalescing (AIC) info */
bool enable_aic;
u16 min_eqd; /* in usecs */
u16 max_eqd; /* in usecs */
u16 cur_eqd; /* in usecs */
struct napi_struct napi;
};
struct be_tx_obj { struct be_tx_obj {
struct be_queue_info q; struct be_queue_info q;
struct be_queue_info cq; struct be_queue_info cq;
...@@ -235,22 +282,6 @@ extern struct ethtool_ops be_ethtool_ops; ...@@ -235,22 +282,6 @@ extern struct ethtool_ops be_ethtool_ops;
#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops)
static inline u32 MODULO(u16 val, u16 limit)
{
BUG_ON(limit & (limit - 1));
return val & (limit - 1);
}
static inline void index_adv(u16 *index, u16 val, u16 limit)
{
*index = MODULO((*index + val), limit);
}
static inline void index_inc(u16 *index, u16 limit)
{
*index = MODULO((*index + 1), limit);
}
#define PAGE_SHIFT_4K 12 #define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
...@@ -339,4 +370,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) ...@@ -339,4 +370,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb)
return val; return val;
} }
extern void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
u16 num_popped);
#endif /* BE_H */ #endif /* BE_H */
This diff is collapsed.
...@@ -101,6 +101,7 @@ struct be_mcc_mailbox { ...@@ -101,6 +101,7 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_FIRMWARE_CONFIG 42 #define OPCODE_COMMON_FIRMWARE_CONFIG 42
#define OPCODE_COMMON_NTWK_INTERFACE_CREATE 50 #define OPCODE_COMMON_NTWK_INTERFACE_CREATE 50
#define OPCODE_COMMON_NTWK_INTERFACE_DESTROY 51 #define OPCODE_COMMON_NTWK_INTERFACE_DESTROY 51
#define OPCODE_COMMON_MCC_DESTROY 53
#define OPCODE_COMMON_CQ_DESTROY 54 #define OPCODE_COMMON_CQ_DESTROY 54
#define OPCODE_COMMON_EQ_DESTROY 55 #define OPCODE_COMMON_EQ_DESTROY 55
#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58
...@@ -269,6 +270,38 @@ struct be_cmd_resp_cq_create { ...@@ -269,6 +270,38 @@ struct be_cmd_resp_cq_create {
u16 rsvd0; u16 rsvd0;
} __packed; } __packed;
/******************** Create MCCQ ***************************/
/* Pseudo amap definition in which each bit of the actual structure is defined
* as a byte: used to calculate offset/shift/mask of each field */
struct amap_mcc_context {
u8 con_index[14];
u8 rsvd0[2];
u8 ring_size[4];
u8 fetch_wrb;
u8 fetch_r2t;
u8 cq_id[10];
u8 prod_index[14];
u8 fid[8];
u8 pdid[9];
u8 valid;
u8 rsvd1[32];
u8 rsvd2[32];
} __packed;
struct be_cmd_req_mcc_create {
struct be_cmd_req_hdr hdr;
u16 num_pages;
u16 rsvd0;
u8 context[sizeof(struct amap_mcc_context) / 8];
struct phys_addr pages[8];
} __packed;
struct be_cmd_resp_mcc_create {
struct be_cmd_resp_hdr hdr;
u16 id;
u16 rsvd0;
} __packed;
/******************** Create TxQ ***************************/ /******************** Create TxQ ***************************/
#define BE_ETH_TX_RING_TYPE_STANDARD 2 #define BE_ETH_TX_RING_TYPE_STANDARD 2
#define BE_ULP1_NUM 1 #define BE_ULP1_NUM 1
...@@ -341,7 +374,8 @@ enum { ...@@ -341,7 +374,8 @@ enum {
QTYPE_EQ = 1, QTYPE_EQ = 1,
QTYPE_CQ, QTYPE_CQ,
QTYPE_TXQ, QTYPE_TXQ,
QTYPE_RXQ QTYPE_RXQ,
QTYPE_MCCQ
}; };
struct be_cmd_req_q_destroy { struct be_cmd_req_q_destroy {
...@@ -657,6 +691,9 @@ extern int be_cmd_cq_create(struct be_ctrl_info *ctrl, ...@@ -657,6 +691,9 @@ extern int be_cmd_cq_create(struct be_ctrl_info *ctrl,
struct be_queue_info *cq, struct be_queue_info *eq, struct be_queue_info *cq, struct be_queue_info *eq,
bool sol_evts, bool no_delay, bool sol_evts, bool no_delay,
int num_cqe_dma_coalesce); int num_cqe_dma_coalesce);
extern int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
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_ctrl_info *ctrl,
struct be_queue_info *txq, struct be_queue_info *txq,
struct be_queue_info *cq); struct be_queue_info *cq);
...@@ -686,3 +723,4 @@ extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, ...@@ -686,3 +723,4 @@ extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl,
extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl,
u32 *tx_fc, u32 *rx_fc); u32 *tx_fc, u32 *rx_fc);
extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num); 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);
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
/* Clear the interrupt for this eq */ /* Clear the interrupt for this eq */
#define DB_EQ_CLR_SHIFT (9) /* bit 9 */ #define DB_EQ_CLR_SHIFT (9) /* bit 9 */
/* Must be 1 */ /* Must be 1 */
#define DB_EQ_EVNT_SHIFT (10) /* bit 10 */ #define DB_EQ_EVNT_SHIFT (10) /* bit 10 */
/* Number of event entries processed */ /* Number of event entries processed */
#define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ #define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */
/* Rearm bit */ /* Rearm bit */
...@@ -88,6 +88,12 @@ ...@@ -88,6 +88,12 @@
/* Number of rx frags posted */ /* Number of rx frags posted */
#define DB_RQ_NUM_POSTED_SHIFT (24) /* bits 24 - 31 */ #define DB_RQ_NUM_POSTED_SHIFT (24) /* bits 24 - 31 */
/********** MCC door bell ************/
#define DB_MCCQ_OFFSET 0x140
#define DB_MCCQ_RING_ID_MASK 0x7FF /* bits 0 - 10 */
/* Number of entries posted */
#define DB_MCCQ_NUM_POSTED_SHIFT (16) /* bits 16 - 29 */
/* /*
* BE descriptors: host memory data structures whose formats * BE descriptors: host memory data structures whose formats
* are hardwired in BE silicon. * are hardwired in BE silicon.
......
...@@ -60,26 +60,6 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, ...@@ -60,26 +60,6 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
return 0; return 0;
} }
static inline void *queue_head_node(struct be_queue_info *q)
{
return q->dma_mem.va + q->head * q->entry_size;
}
static inline void *queue_tail_node(struct be_queue_info *q)
{
return q->dma_mem.va + q->tail * q->entry_size;
}
static inline void queue_head_inc(struct be_queue_info *q)
{
index_inc(&q->head, q->len);
}
static inline void queue_tail_inc(struct be_queue_info *q)
{
index_inc(&q->tail, q->len);
}
static void be_intr_set(struct be_ctrl_info *ctrl, bool enable) static void be_intr_set(struct be_ctrl_info *ctrl, bool enable)
{ {
u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
...@@ -127,7 +107,7 @@ static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid, ...@@ -127,7 +107,7 @@ static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid,
iowrite32(val, ctrl->db + DB_EQ_OFFSET); iowrite32(val, ctrl->db + DB_EQ_OFFSET);
} }
static void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid,
bool arm, u16 num_popped) bool arm, u16 num_popped)
{ {
u32 val = 0; u32 val = 0;
...@@ -960,10 +940,8 @@ static void be_post_rx_frags(struct be_adapter *adapter) ...@@ -960,10 +940,8 @@ static void be_post_rx_frags(struct be_adapter *adapter)
return; return;
} }
static struct be_eth_tx_compl * static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq)
be_tx_compl_get(struct be_adapter *adapter)
{ {
struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq); struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq);
if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0) if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0)
...@@ -1051,6 +1029,59 @@ static void be_tx_q_clean(struct be_adapter *adapter) ...@@ -1051,6 +1029,59 @@ static void be_tx_q_clean(struct be_adapter *adapter)
} }
} }
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;
if (q->created)
be_cmd_q_destroy(ctrl, q, QTYPE_MCCQ);
be_queue_free(adapter, q);
q = &ctrl->mcc_obj.cq;
if (q->created)
be_cmd_q_destroy(ctrl, q, QTYPE_CQ);
be_queue_free(adapter, q);
}
/* Must be called only after TX qs are created as MCC shares TX EQ */
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;
if (be_queue_alloc(adapter, cq, MCC_CQ_LEN,
sizeof(struct be_mcc_cq_entry)))
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))
goto mcc_cq_free;
/* Alloc MCC queue */
q = &ctrl->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))
goto mcc_q_free;
return 0;
mcc_q_free:
be_queue_free(adapter, q);
mcc_cq_destroy:
be_cmd_q_destroy(ctrl, cq, QTYPE_CQ);
mcc_cq_free:
be_queue_free(adapter, cq);
err:
return -1;
}
static void be_tx_queues_destroy(struct be_adapter *adapter) static void be_tx_queues_destroy(struct be_adapter *adapter)
{ {
struct be_queue_info *q; struct be_queue_info *q;
...@@ -1263,7 +1294,7 @@ static irqreturn_t be_msix_rx(int irq, void *dev) ...@@ -1263,7 +1294,7 @@ static irqreturn_t be_msix_rx(int irq, void *dev)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t be_msix_tx(int irq, void *dev) static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
{ {
struct be_adapter *adapter = dev; struct be_adapter *adapter = dev;
...@@ -1324,40 +1355,51 @@ int be_poll_rx(struct napi_struct *napi, int budget) ...@@ -1324,40 +1355,51 @@ int be_poll_rx(struct napi_struct *napi, int budget)
return work_done; return work_done;
} }
/* For TX we don't honour budget; consume everything */ void be_process_tx(struct be_adapter *adapter)
int be_poll_tx(struct napi_struct *napi, int budget)
{ {
struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); struct be_queue_info *txq = &adapter->tx_obj.q;
struct be_adapter *adapter = struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
container_of(tx_eq, struct be_adapter, tx_eq);
struct be_tx_obj *tx_obj = &adapter->tx_obj;
struct be_queue_info *tx_cq = &tx_obj->cq;
struct be_queue_info *txq = &tx_obj->q;
struct be_eth_tx_compl *txcp; struct be_eth_tx_compl *txcp;
u32 num_cmpl = 0; u32 num_cmpl = 0;
u16 end_idx; u16 end_idx;
while ((txcp = be_tx_compl_get(adapter))) { while ((txcp = be_tx_compl_get(tx_cq))) {
end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
wrb_index, txcp); wrb_index, txcp);
be_tx_compl_process(adapter, end_idx); be_tx_compl_process(adapter, end_idx);
num_cmpl++; num_cmpl++;
} }
/* As Tx wrbs have been freed up, wake up netdev queue if if (num_cmpl) {
* it was stopped due to lack of tx wrbs. be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl);
*/
if (netif_queue_stopped(adapter->netdev) && /* As Tx wrbs have been freed up, wake up netdev queue if
* it was stopped due to lack of tx wrbs.
*/
if (netif_queue_stopped(adapter->netdev) &&
atomic_read(&txq->used) < txq->len / 2) { atomic_read(&txq->used) < txq->len / 2) {
netif_wake_queue(adapter->netdev); netif_wake_queue(adapter->netdev);
}
drvr_stats(adapter)->be_tx_events++;
drvr_stats(adapter)->be_tx_compl += num_cmpl;
} }
}
/* As TX and MCC share the same EQ check for both TX and MCC completions.
* For TX/MCC we don't honour budget; consume everything
*/
static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
{
struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);
struct be_adapter *adapter =
container_of(tx_eq, struct be_adapter, tx_eq);
napi_complete(napi); napi_complete(napi);
be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl); be_process_tx(adapter);
drvr_stats(adapter)->be_tx_events++; be_process_mcc(&adapter->ctrl);
drvr_stats(adapter)->be_tx_compl += num_cmpl;
return 1; return 1;
} }
...@@ -1419,7 +1461,7 @@ static int be_msix_register(struct be_adapter *adapter) ...@@ -1419,7 +1461,7 @@ static int be_msix_register(struct be_adapter *adapter)
sprintf(tx_eq->desc, "%s-tx", netdev->name); sprintf(tx_eq->desc, "%s-tx", netdev->name);
vec = be_msix_vec_get(adapter, tx_eq->q.id); vec = be_msix_vec_get(adapter, tx_eq->q.id);
status = request_irq(vec, be_msix_tx, 0, tx_eq->desc, adapter); status = request_irq(vec, be_msix_tx_mcc, 0, tx_eq->desc, adapter);
if (status) if (status)
goto err; goto err;
...@@ -1495,6 +1537,34 @@ static int be_open(struct net_device *netdev) ...@@ -1495,6 +1537,34 @@ static int be_open(struct net_device *netdev)
struct be_ctrl_info *ctrl = &adapter->ctrl; struct be_ctrl_info *ctrl = &adapter->ctrl;
struct be_eq_obj *rx_eq = &adapter->rx_eq; struct be_eq_obj *rx_eq = &adapter->rx_eq;
struct be_eq_obj *tx_eq = &adapter->tx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq;
/* First time posting */
be_post_rx_frags(adapter);
napi_enable(&rx_eq->napi);
napi_enable(&tx_eq->napi);
be_irq_register(adapter);
be_intr_set(ctrl, 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);
/* Rx compl queue may be in unarmed state; rearm it */
be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0);
be_link_status_update(adapter);
schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
return 0;
}
static int be_setup(struct be_adapter *adapter)
{
struct be_ctrl_info *ctrl = &adapter->ctrl;
struct net_device *netdev = adapter->netdev;
u32 if_flags; u32 if_flags;
int status; int status;
...@@ -1521,29 +1591,14 @@ static int be_open(struct net_device *netdev) ...@@ -1521,29 +1591,14 @@ static int be_open(struct net_device *netdev)
if (status != 0) if (status != 0)
goto tx_qs_destroy; goto tx_qs_destroy;
/* First time posting */ status = be_mcc_queues_create(adapter);
be_post_rx_frags(adapter); if (status != 0)
goto rx_qs_destroy;
napi_enable(&rx_eq->napi);
napi_enable(&tx_eq->napi);
be_irq_register(adapter);
be_intr_set(ctrl, true);
/* The evt queues are created in the 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);
/* The compl queues are created in the unarmed state; arm them */
be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0);
be_cq_notify(ctrl, adapter->tx_obj.cq.id, true, 0);
be_link_status_update(adapter);
schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
return 0; return 0;
rx_qs_destroy:
be_rx_queues_destroy(adapter);
tx_qs_destroy: tx_qs_destroy:
be_tx_queues_destroy(adapter); be_tx_queues_destroy(adapter);
if_destroy: if_destroy:
...@@ -1552,6 +1607,19 @@ do_none: ...@@ -1552,6 +1607,19 @@ do_none:
return status; return status;
} }
static int be_clear(struct be_adapter *adapter)
{
struct be_ctrl_info *ctrl = &adapter->ctrl;
be_rx_queues_destroy(adapter);
be_tx_queues_destroy(adapter);
be_cmd_if_destroy(ctrl, adapter->if_handle);
be_mcc_queues_destroy(adapter);
return 0;
}
static int be_close(struct net_device *netdev) static int be_close(struct net_device *netdev)
{ {
struct be_adapter *adapter = netdev_priv(netdev); struct be_adapter *adapter = netdev_priv(netdev);
...@@ -1581,10 +1649,6 @@ static int be_close(struct net_device *netdev) ...@@ -1581,10 +1649,6 @@ static int be_close(struct net_device *netdev)
napi_disable(&rx_eq->napi); napi_disable(&rx_eq->napi);
napi_disable(&tx_eq->napi); napi_disable(&tx_eq->napi);
be_rx_queues_destroy(adapter);
be_tx_queues_destroy(adapter);
be_cmd_if_destroy(ctrl, adapter->if_handle);
return 0; return 0;
} }
...@@ -1673,7 +1737,7 @@ static void be_netdev_init(struct net_device *netdev) ...@@ -1673,7 +1737,7 @@ static void be_netdev_init(struct net_device *netdev)
netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx, netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx,
BE_NAPI_WEIGHT); BE_NAPI_WEIGHT);
netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx, netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
BE_NAPI_WEIGHT); BE_NAPI_WEIGHT);
netif_carrier_off(netdev); netif_carrier_off(netdev);
...@@ -1755,7 +1819,9 @@ static int be_ctrl_init(struct be_adapter *adapter) ...@@ -1755,7 +1819,9 @@ static int be_ctrl_init(struct be_adapter *adapter)
mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
spin_lock_init(&ctrl->cmd_lock); spin_lock_init(&ctrl->mbox_lock);
spin_lock_init(&ctrl->mcc_lock);
spin_lock_init(&ctrl->mcc_cq_lock);
val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) & ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) &
...@@ -1793,6 +1859,8 @@ static void __devexit be_remove(struct pci_dev *pdev) ...@@ -1793,6 +1859,8 @@ static void __devexit be_remove(struct pci_dev *pdev)
unregister_netdev(adapter->netdev); unregister_netdev(adapter->netdev);
be_clear(adapter);
be_stats_cleanup(adapter); be_stats_cleanup(adapter);
be_ctrl_cleanup(adapter); be_ctrl_cleanup(adapter);
...@@ -1890,13 +1958,18 @@ static int __devinit be_probe(struct pci_dev *pdev, ...@@ -1890,13 +1958,18 @@ static int __devinit be_probe(struct pci_dev *pdev,
be_netdev_init(netdev); be_netdev_init(netdev);
SET_NETDEV_DEV(netdev, &adapter->pdev->dev); SET_NETDEV_DEV(netdev, &adapter->pdev->dev);
status = be_setup(adapter);
if (status)
goto stats_clean;
status = register_netdev(netdev); status = register_netdev(netdev);
if (status != 0) if (status != 0)
goto stats_clean; goto unsetup;
dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num); dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
return 0; return 0;
unsetup:
be_clear(adapter);
stats_clean: stats_clean:
be_stats_cleanup(adapter); be_stats_cleanup(adapter);
ctrl_clean: ctrl_clean:
...@@ -1921,6 +1994,7 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -1921,6 +1994,7 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
if (netif_running(netdev)) { if (netif_running(netdev)) {
rtnl_lock(); rtnl_lock();
be_close(netdev); be_close(netdev);
be_clear(adapter);
rtnl_unlock(); rtnl_unlock();
} }
...@@ -1947,6 +2021,7 @@ static int be_resume(struct pci_dev *pdev) ...@@ -1947,6 +2021,7 @@ static int be_resume(struct pci_dev *pdev)
if (netif_running(netdev)) { if (netif_running(netdev)) {
rtnl_lock(); rtnl_lock();
be_setup(adapter);
be_open(netdev); be_open(netdev);
rtnl_unlock(); rtnl_unlock();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment