case CPL_SGE_EGR_UPDATE: {
/*
- * We've received an Egress Queue status update message.
- * We get these, as the SGE is currently configured, when
- * the firmware passes certain points in processing our
- * TX Ethernet Queue. We use these updates to determine
- * when we may need to restart a TX Ethernet Queue which
- * was stopped for lack of free slots ...
+ * We've received an Egress Queue Status Update message. We
+ * get these, if the SGE is configured to send these when the
+ * firmware passes certain points in processing our TX
+ * Ethernet Queue or if we make an explicit request for one.
+ * We use these updates to determine when we may need to
+ * restart a TX Ethernet Queue which was stopped for lack of
+ * free TX Queue Descriptors ...
*/
const struct cpl_sge_egr_update *p = (void *)cpl;
unsigned int qid = EGR_QID(be32_to_cpu(p->opcode_qid));
struct sge_txq *tq;
struct sge_eth_txq *txq;
unsigned int eq_idx;
- int hw_cidx, reclaimable, in_use;
/*
* Perform sanity checking on the Queue ID to make sure it
}
/*
- * Skip TX Queues which aren't stopped.
- */
- if (likely(!netif_tx_queue_stopped(txq->txq)))
- break;
-
- /*
- * Skip stopped TX Queues which have more than half of their
- * DMA rings occupied with unacknowledged writes.
- */
- hw_cidx = be16_to_cpu(txq->q.stat->cidx);
- reclaimable = hw_cidx - txq->q.cidx;
- if (reclaimable < 0)
- reclaimable += txq->q.size;
- in_use = txq->q.in_use - reclaimable;
- if (in_use >= txq->q.size/2)
- break;
-
- /*
* Restart a stopped TX Queue which has less than half of its
* TX ring in use ...
*/
struct port_info *pi = netdev_priv(dev);
struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset];
struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset];
- int nqsets = (adapter->flags & USING_MSIX) ? pi->nqsets : 1;
int qs;
- for (qs = 0; qs < nqsets; qs++, rxq++, txq++) {
+ for (qs = 0; qs < pi->nqsets; qs++, rxq++, txq++) {
err = t4vf_sge_alloc_rxq(adapter, &rxq->rspq, false,
dev, msix++,
&rxq->fl, t4vf_ethrx_handler);
struct port_info *pi = netdev_priv(dev);
struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset];
struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset];
- int nqsets = (adapter->flags & USING_MSIX) ? pi->nqsets : 1;
int qs;
- for (qs = 0; qs < nqsets; qs++, rxq++, txq++) {
+ for (qs = 0; qs < pi->nqsets; qs++, rxq++, txq++) {
IQ_MAP(s, rxq->rspq.abs_id) = &rxq->rspq;
EQ_MAP(s, txq->q.abs_id) = &txq->q;
/*
* Note that this interface is up and start everything up ...
*/
- dev->real_num_tx_queues = pi->nqsets;
+ netif_set_real_num_tx_queues(dev, pi->nqsets);
+ err = netif_set_real_num_rx_queues(dev, pi->nqsets);
+ if (err)
+ return err;
set_bit(pi->port_id, &adapter->open_device_map);
- link_start(dev);
+ err = link_start(dev);
+ if (err)
+ return err;
netif_tx_start_all_queues(dev);
return 0;
}
return 0;
}
-/*
- * Return a TX Queue on which to send the specified skb.
- */
-static u16 cxgb4vf_select_queue(struct net_device *dev, struct sk_buff *skb)
-{
- /*
- * XXX For now just use the default hash but we probably want to
- * XXX look at other possibilities ...
- */
- return skb_tx_hash(dev, skb);
-}
-
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
* Poll all of our receive queues. This is called outside of normal interrupt
(rxq[qs].rspq.netdev
? rxq[qs].rspq.netdev->name
: "N/A"));
- R3("u", "RspQNullInts", rspq.unhandled_irqs);
+ R3("u", "RspQNullInts:", rspq.unhandled_irqs);
R("RxPackets:", stats.pkts);
R("RxCSO:", stats.rx_cso);
R("VLANxtract:", stats.vlan_ex);
const struct sge_rspq *evtq = &adapter->sge.fw_evtq;
seq_printf(seq, "%-8s %16s\n", "QType:", "FW event queue");
- /* no real response queue statistics available to display */
+ seq_printf(seq, "%-16s %8u\n", "RspQNullInts:",
+ evtq->unhandled_irqs);
seq_printf(seq, "%-16s %8u\n", "RspQ CIdx:", evtq->cidx);
seq_printf(seq, "%-16s %8u\n", "RspQ Gen:", evtq->gen);
} else if (r == 1) {
const struct sge_rspq *intrq = &adapter->sge.intrq;
seq_printf(seq, "%-8s %16s\n", "QType:", "Interrupt Queue");
- /* no real response queue statistics available to display */
+ seq_printf(seq, "%-16s %8u\n", "RspQNullInts:",
+ intrq->unhandled_irqs);
seq_printf(seq, "%-16s %8u\n", "RspQ CIdx:", intrq->cidx);
seq_printf(seq, "%-16s %8u\n", "RspQ Gen:", intrq->gen);
}
}
/*
+ * Some environments do not properly handle PCIE FLRs -- e.g. in Linux
+ * 2.6.31 and later we can't call pci_reset_function() in order to
+ * issue an FLR because of a self- deadlock on the device semaphore.
+ * Meanwhile, the OS infrastructure doesn't issue FLRs in all the
+ * cases where they're needed -- for instance, some versions of KVM
+ * fail to reset "Assigned Devices" when the VM reboots. Therefore we
+ * use the firmware based reset in order to reset any per function
+ * state.
+ */
+ err = t4vf_fw_reset(adapter);
+ if (err < 0) {
+ dev_err(adapter->pdev_dev, "FW reset failed: err=%d\n", err);
+ return err;
+ }
+
+ /*
* Grab basic operational parameters. These will predominantly have
* been set up by the Physical Function Driver or will be hard coded
* into the adapter. We just have to live with them ... Note that
.ndo_get_stats = cxgb4vf_get_stats,
.ndo_set_rx_mode = cxgb4vf_set_rxmode,
.ndo_set_mac_address = cxgb4vf_set_mac_addr,
- .ndo_select_queue = cxgb4vf_select_queue,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = cxgb4vf_do_ioctl,
.ndo_change_mtu = cxgb4vf_change_mtu,
version_printed = 1;
}
+
/*
- * Reserve PCI resources for the device. If we can't get them some
- * other driver may have already claimed the device ...
+ * Initialize generic PCI device state.
*/
- err = pci_request_regions(pdev, KBUILD_MODNAME);
+ err = pci_enable_device(pdev);
if (err) {
- dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+ dev_err(&pdev->dev, "cannot enable PCI device\n");
return err;
}
/*
- * Initialize generic PCI device state.
+ * Reserve PCI resources for the device. If we can't get them some
+ * other driver may have already claimed the device ...
*/
- err = pci_enable_device(pdev);
+ err = pci_request_regions(pdev, KBUILD_MODNAME);
if (err) {
- dev_err(&pdev->dev, "cannot enable PCI device\n");
- goto err_release_regions;
+ dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+ goto err_disable_device;
}
/*
if (err) {
dev_err(&pdev->dev, "unable to obtain 64-bit DMA for"
" coherent allocations\n");
- goto err_disable_device;
+ goto err_release_regions;
}
pci_using_dac = 1;
} else {
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (err != 0) {
dev_err(&pdev->dev, "no usable DMA configuration\n");
- goto err_disable_device;
+ goto err_release_regions;
}
pci_using_dac = 0;
}
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
if (!adapter) {
err = -ENOMEM;
- goto err_disable_device;
+ goto err_release_regions;
}
pci_set_drvdata(pdev, adapter);
adapter->pdev = pdev;
pi->xact_addr_filt = -1;
pi->rx_offload = RX_CSO;
netif_carrier_off(netdev);
- netif_tx_stop_all_queues(netdev);
netdev->irq = pdev->irq;
netdev->features = (NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
netdev->do_ioctl = cxgb4vf_do_ioctl;
netdev->change_mtu = cxgb4vf_change_mtu;
netdev->set_mac_address = cxgb4vf_set_mac_addr;
- netdev->select_queue = cxgb4vf_select_queue;
#ifdef CONFIG_NET_POLL_CONTROLLER
netdev->poll_controller = cxgb4vf_poll_controller;
#endif
kfree(adapter);
pci_set_drvdata(pdev, NULL);
-err_disable_device:
- pci_disable_device(pdev);
- pci_clear_master(pdev);
-
err_release_regions:
pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
+ pci_clear_master(pdev);
+
+err_disable_device:
+ pci_disable_device(pdev);
err_out:
return err;
CH_DEVICE(0x4800, 0), /* T440-dbg */
CH_DEVICE(0x4801, 0), /* T420-cr */
CH_DEVICE(0x4802, 0), /* T422-cr */
+ CH_DEVICE(0x4803, 0), /* T440-cr */
+ CH_DEVICE(0x4804, 0), /* T420-bch */
+ CH_DEVICE(0x4805, 0), /* T440-bch */
+ CH_DEVICE(0x4806, 0), /* T460-ch */
+ CH_DEVICE(0x4807, 0), /* T420-so */
+ CH_DEVICE(0x4808, 0), /* T420-cx */
+ CH_DEVICE(0x4809, 0), /* T420-bt */
+ CH_DEVICE(0x480a, 0), /* T404-bt */
{ 0, }
};