(addr[5]);
QPRINTK(qdev, IFUP, INFO,
- "Adding %s address %02x:%02x:%02x:%02x:%02x:%02x"
+ "Adding %s address %pM"
" at index %d in the CAM.\n",
((type ==
MAC_ADDR_TYPE_MULTI_MAC) ? "MULTICAST" :
- "UNICAST"), addr[0], addr[1], addr[2], addr[3],
- addr[4], addr[5], index);
+ "UNICAST"), addr, index);
status =
ql_wait_reg_rdy(qdev,
* incremented everytime we queue a worker and decremented everytime
* a worker finishes. Once it hits zero we enable the interrupt.
*/
-void ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
+u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
{
- if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags)))
+ u32 var = 0;
+ unsigned long hw_flags = 0;
+ struct intr_context *ctx = qdev->intr_context + intr;
+
+ if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr)) {
+ /* Always enable if we're MSIX multi interrupts and
+ * it's not the default (zeroeth) interrupt.
+ */
ql_write32(qdev, INTR_EN,
- qdev->intr_context[intr].intr_en_mask);
- else {
- if (qdev->legacy_check)
- spin_lock(&qdev->legacy_lock);
- if (atomic_dec_and_test(&qdev->intr_context[intr].irq_cnt)) {
- QPRINTK(qdev, INTR, ERR, "Enabling interrupt %d.\n",
- intr);
- ql_write32(qdev, INTR_EN,
- qdev->intr_context[intr].intr_en_mask);
- } else {
- QPRINTK(qdev, INTR, ERR,
- "Skip enable, other queue(s) are active.\n");
- }
- if (qdev->legacy_check)
- spin_unlock(&qdev->legacy_lock);
+ ctx->intr_en_mask);
+ var = ql_read32(qdev, STS);
+ return var;
+ }
+
+ spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+ if (atomic_dec_and_test(&ctx->irq_cnt)) {
+ ql_write32(qdev, INTR_EN,
+ ctx->intr_en_mask);
+ var = ql_read32(qdev, STS);
}
+ spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+ return var;
}
static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
{
u32 var = 0;
+ unsigned long hw_flags;
+ struct intr_context *ctx;
- if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags)))
- goto exit;
- else if (!atomic_read(&qdev->intr_context[intr].irq_cnt)) {
+ /* HW disables for us if we're MSIX multi interrupts and
+ * it's not the default (zeroeth) interrupt.
+ */
+ if (likely(test_bit(QL_MSIX_ENABLED, &qdev->flags) && intr))
+ return 0;
+
+ ctx = qdev->intr_context + intr;
+ spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+ if (!atomic_read(&ctx->irq_cnt)) {
ql_write32(qdev, INTR_EN,
- qdev->intr_context[intr].intr_dis_mask);
+ ctx->intr_dis_mask);
var = ql_read32(qdev, STS);
}
- atomic_inc(&qdev->intr_context[intr].irq_cnt);
-exit:
+ atomic_inc(&ctx->irq_cnt);
+ spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
return var;
}
* and enables only if the result is zero.
* So we precharge it here.
*/
- atomic_set(&qdev->intr_context[i].irq_cnt, 1);
+ if (unlikely(!test_bit(QL_MSIX_ENABLED, &qdev->flags) ||
+ i == 0))
+ atomic_set(&qdev->intr_context[i].irq_cnt, 1);
ql_enable_completion_interrupt(qdev, i);
}
}
-int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data)
+static int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data)
{
int status = 0;
/* wait for reg to come ready */
}
/* Get the next large buffer. */
-struct bq_desc *ql_get_curr_lbuf(struct rx_ring *rx_ring)
+static struct bq_desc *ql_get_curr_lbuf(struct rx_ring *rx_ring)
{
struct bq_desc *lbq_desc = &rx_ring->lbq[rx_ring->lbq_curr_idx];
rx_ring->lbq_curr_idx++;
}
/* Get the next small buffer. */
-struct bq_desc *ql_get_curr_sbuf(struct rx_ring *rx_ring)
+static struct bq_desc *ql_get_curr_sbuf(struct rx_ring *rx_ring)
{
struct bq_desc *sbq_desc = &rx_ring->sbq[rx_ring->sbq_curr_idx];
rx_ring->sbq_curr_idx++;
return NETDEV_TX_BUSY;
}
-void ql_realign_skb(struct sk_buff *skb, int len)
+static void ql_realign_skb(struct sk_buff *skb, int len)
{
void *temp_addr = skb->data;
"Passing a normal packet upstream.\n");
netif_rx(skb);
}
- ndev->last_rx = jiffies;
}
/* Process an outbound completion from an rx ring. */
rx_ring->cq_id);
if (work_done < budget) {
- __netif_rx_complete(qdev->ndev, napi);
+ __netif_rx_complete(napi);
ql_enable_completion_interrupt(qdev, rx_ring->irq);
}
return work_done;
{
struct rx_ring *rx_ring = dev_id;
struct ql_adapter *qdev = rx_ring->qdev;
- netif_rx_schedule(qdev->ndev, &rx_ring->napi);
+ netif_rx_schedule(&rx_ring->napi);
return IRQ_HANDLED;
}
-/* We check here to see if we're already handling a legacy
- * interrupt. If we are, then it must belong to another
- * chip with which we're sharing the interrupt line.
- */
-int ql_legacy_check(struct ql_adapter *qdev)
-{
- int err;
- spin_lock(&qdev->legacy_lock);
- err = atomic_read(&qdev->intr_context[0].irq_cnt);
- spin_unlock(&qdev->legacy_lock);
- return err;
-}
-
/* This handles a fatal error, MPI activity, and the default
* rx_ring in an MSI-X multiple vector environment.
* In MSI/Legacy environment it also process the rest of
int i;
int work_done = 0;
- if (qdev->legacy_check && qdev->legacy_check(qdev)) {
- QPRINTK(qdev, INTR, INFO, "Already busy, not our interrupt.\n");
- return IRQ_NONE; /* Not our interrupt */
+ spin_lock(&qdev->hw_lock);
+ if (atomic_read(&qdev->intr_context[0].irq_cnt)) {
+ QPRINTK(qdev, INTR, DEBUG, "Shared Interrupt, Not ours!\n");
+ spin_unlock(&qdev->hw_lock);
+ return IRQ_NONE;
}
+ spin_unlock(&qdev->hw_lock);
- var = ql_read32(qdev, STS);
+ var = ql_disable_completion_interrupt(qdev, intr_context->intr);
/*
* Check for fatal error.
&rx_ring->rx_work,
0);
else
- netif_rx_schedule(qdev->ndev,
- &rx_ring->napi);
+ netif_rx_schedule(&rx_ring->napi);
work_done++;
}
}
}
+ ql_enable_completion_interrupt(qdev, intr_context->intr);
return work_done ? IRQ_HANDLED : IRQ_NONE;
}
return -ENOMEM;
}
-void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+static void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
{
int i;
struct bq_desc *lbq_desc;
return -ENOMEM;
}
-void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
{
int i;
struct bq_desc *sbq_desc;
rx_ring->sbq_base_indirect_dma = shadow_reg_dma;
/* PCI doorbell mem area + 0x00 for consumer index register */
- rx_ring->cnsmr_idx_db_reg = (u32 *) doorbell_area;
+ rx_ring->cnsmr_idx_db_reg = (u32 __iomem *) doorbell_area;
rx_ring->cnsmr_idx = 0;
rx_ring->curr_entry = rx_ring->cq_base;
rx_ring->valid_db_reg = doorbell_area + 0x04;
/* PCI doorbell mem area + 0x18 for large buffer consumer */
- rx_ring->lbq_prod_idx_db_reg = (u32 *) (doorbell_area + 0x18);
+ rx_ring->lbq_prod_idx_db_reg = (u32 __iomem *) (doorbell_area + 0x18);
/* PCI doorbell mem area + 0x1c */
- rx_ring->sbq_prod_idx_db_reg = (u32 *) (doorbell_area + 0x1c);
+ rx_ring->sbq_prod_idx_db_reg = (u32 __iomem *) (doorbell_area + 0x1c);
memset((void *)cqicb, 0, sizeof(struct cqicb));
cqicb->msix_vect = rx_ring->irq;
* Assign doorbell registers for this tx_ring.
*/
/* TX PCI doorbell mem area for tx producer index */
- tx_ring->prod_idx_db_reg = (u32 *) doorbell_area;
+ tx_ring->prod_idx_db_reg = (u32 __iomem *) doorbell_area;
tx_ring->prod_idx = 0;
/* TX PCI doorbell mem area + 0x04 */
tx_ring->valid_db_reg = doorbell_area + 0x04;
}
}
irq_type = LEG_IRQ;
- spin_lock_init(&qdev->legacy_lock);
- qdev->legacy_check = ql_legacy_check;
QPRINTK(qdev, IFUP, DEBUG, "Running with legacy interrupts.\n");
}
qdev->chip_rev_id >> 4 & 0x0000000f,
qdev->chip_rev_id >> 8 & 0x0000000f,
qdev->chip_rev_id >> 12 & 0x0000000f);
- QPRINTK(qdev, PROBE, INFO,
- "MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
- ndev->dev_addr[0], ndev->dev_addr[1],
- ndev->dev_addr[2], ndev->dev_addr[3], ndev->dev_addr[4],
- ndev->dev_addr[5]);
+ QPRINTK(qdev, PROBE, INFO, "MAC address %pM\n", ndev->dev_addr);
}
static int ql_adapter_down(struct ql_adapter *qdev)
{
struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
struct sockaddr *addr = p;
+ int ret = 0;
if (netif_running(ndev))
return -EBUSY;
if (ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr,
MAC_ADDR_TYPE_CAM_MAC, qdev->func)) {/* Unicast */
QPRINTK(qdev, HW, ERR, "Failed to load MAC address.\n");
- return -1;
+ ret = -1;
}
spin_unlock(&qdev->hw_lock);
- return 0;
+ return ret;
}
static void qlge_tx_timeout(struct net_device *ndev)
qdev->q_workqueue = NULL;
}
if (qdev->reg_base)
- iounmap((void *)qdev->reg_base);
+ iounmap(qdev->reg_base);
if (qdev->doorbell_area)
iounmap(qdev->doorbell_area);
pci_release_regions(pdev);
return err;
}
+
+static const struct net_device_ops qlge_netdev_ops = {
+ .ndo_open = qlge_open,
+ .ndo_stop = qlge_close,
+ .ndo_start_xmit = qlge_send,
+ .ndo_change_mtu = qlge_change_mtu,
+ .ndo_get_stats = qlge_get_stats,
+ .ndo_set_multicast_list = qlge_set_multicast_list,
+ .ndo_set_mac_address = qlge_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_tx_timeout = qlge_tx_timeout,
+ .ndo_vlan_rx_register = ql_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = ql_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ql_vlan_rx_kill_vid,
+};
+
static int __devinit qlge_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_entry)
{
*/
ndev->tx_queue_len = qdev->tx_ring_size;
ndev->irq = pdev->irq;
- ndev->open = qlge_open;
- ndev->stop = qlge_close;
- ndev->hard_start_xmit = qlge_send;
+
+ ndev->netdev_ops = &qlge_netdev_ops;
SET_ETHTOOL_OPS(ndev, &qlge_ethtool_ops);
- ndev->change_mtu = qlge_change_mtu;
- ndev->get_stats = qlge_get_stats;
- ndev->set_multicast_list = qlge_set_multicast_list;
- ndev->set_mac_address = qlge_set_mac_address;
- ndev->tx_timeout = qlge_tx_timeout;
ndev->watchdog_timeo = 10 * HZ;
- ndev->vlan_rx_register = ql_vlan_rx_register;
- ndev->vlan_rx_add_vid = ql_vlan_rx_add_vid;
- ndev->vlan_rx_kill_vid = ql_vlan_rx_kill_vid;
+
err = register_netdev(ndev);
if (err) {
dev_err(&pdev->dev, "net device registration failed.\n");