Skip to content

Commit

Permalink
Merge tag 'ntb-3.13' of git://github.com/jonmason/ntb
Browse files Browse the repository at this point in the history
Pull non-transparent bridge updates from Jon Mason:
 "NTB driver bug fixes to address a missed call to pci_enable_msix,
  NTB-RP Link Up issue, Xeon Doorbell errata workaround, ntb_transport
  link down race, and correct dmaengine_get/put usage.

  Also, clean-ups to remove duplicate defines and document a hardware
  errata.  Finally, some changes to improve performance"

* tag 'ntb-3.13' of git://github.com/jonmason/ntb:
  NTB: Disable interrupts and poll under high load
  NTB: Enable Snoop on Primary Side
  NTB: Document HW errata
  NTB: remove duplicate defines
  NTB: correct dmaengine_get/put usage
  NTB: Fix ntb_transport link down race
  ntb: Fix missed call to pci_enable_msix()
  NTB: Fix NTB-RP Link Up
  NTB: Xeon Doorbell errata workaround
  • Loading branch information
torvalds committed Nov 26, 2013
2 parents b975dc3 + e8aeb60 commit b954851
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 65 deletions.
121 changes: 103 additions & 18 deletions drivers/ntb/ntb_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,24 @@ void ntb_unregister_event_callback(struct ntb_device *ndev)
ndev->event_cb = NULL;
}

static void ntb_irq_work(unsigned long data)
{
struct ntb_db_cb *db_cb = (struct ntb_db_cb *)data;
int rc;

rc = db_cb->callback(db_cb->data, db_cb->db_num);
if (rc)
tasklet_schedule(&db_cb->irq_work);
else {
struct ntb_device *ndev = db_cb->ndev;
unsigned long mask;

mask = readw(ndev->reg_ofs.ldb_mask);
clear_bit(db_cb->db_num * ndev->bits_per_vector, &mask);
writew(mask, ndev->reg_ofs.ldb_mask);
}
}

/**
* ntb_register_db_callback() - register a callback for doorbell interrupt
* @ndev: pointer to ntb_device instance
Expand All @@ -155,7 +173,7 @@ void ntb_unregister_event_callback(struct ntb_device *ndev)
* RETURNS: An appropriate -ERRNO error value on error, or zero for success.
*/
int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx,
void *data, void (*func)(void *data, int db_num))
void *data, int (*func)(void *data, int db_num))
{
unsigned long mask;

Expand All @@ -166,6 +184,10 @@ int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx,

ndev->db_cb[idx].callback = func;
ndev->db_cb[idx].data = data;
ndev->db_cb[idx].ndev = ndev;

tasklet_init(&ndev->db_cb[idx].irq_work, ntb_irq_work,
(unsigned long) &ndev->db_cb[idx]);

/* unmask interrupt */
mask = readw(ndev->reg_ofs.ldb_mask);
Expand Down Expand Up @@ -194,6 +216,8 @@ void ntb_unregister_db_callback(struct ntb_device *ndev, unsigned int idx)
set_bit(idx * ndev->bits_per_vector, &mask);
writew(mask, ndev->reg_ofs.ldb_mask);

tasklet_disable(&ndev->db_cb[idx].irq_work);

ndev->db_cb[idx].callback = NULL;
}

Expand Down Expand Up @@ -678,6 +702,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
return -EINVAL;

ndev->limits.max_mw = SNB_ERRATA_MAX_MW;
ndev->limits.max_db_bits = SNB_MAX_DB_BITS;
ndev->reg_ofs.spad_write = ndev->mw[1].vbase +
SNB_SPAD_OFFSET;
ndev->reg_ofs.rdb = ndev->mw[1].vbase +
Expand All @@ -688,8 +713,21 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
*/
writeq(ndev->mw[1].bar_sz + 0x1000, ndev->reg_base +
SNB_PBAR4LMT_OFFSET);
/* HW errata on the Limit registers. They can only be
* written when the base register is 4GB aligned and
* < 32bit. This should already be the case based on the
* driver defaults, but write the Limit registers first
* just in case.
*/
} else {
ndev->limits.max_mw = SNB_MAX_MW;

/* HW Errata on bit 14 of b2bdoorbell register. Writes
* will not be mirrored to the remote system. Shrink
* the number of bits by one, since bit 14 is the last
* bit.
*/
ndev->limits.max_db_bits = SNB_MAX_DB_BITS - 1;
ndev->reg_ofs.spad_write = ndev->reg_base +
SNB_B2B_SPAD_OFFSET;
ndev->reg_ofs.rdb = ndev->reg_base +
Expand All @@ -699,6 +737,12 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
* something silly
*/
writeq(0, ndev->reg_base + SNB_PBAR4LMT_OFFSET);
/* HW errata on the Limit registers. They can only be
* written when the base register is 4GB aligned and
* < 32bit. This should already be the case based on the
* driver defaults, but write the Limit registers first
* just in case.
*/
}

/* The Xeon errata workaround requires setting SBAR Base
Expand Down Expand Up @@ -769,6 +813,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
* have an equal amount.
*/
ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2;
ndev->limits.max_db_bits = SNB_MAX_DB_BITS;
/* Note: The SDOORBELL is the cause of the errata. You REALLY
* don't want to touch it.
*/
Expand All @@ -793,6 +838,7 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
* have an equal amount.
*/
ndev->limits.max_spads = SNB_MAX_COMPAT_SPADS / 2;
ndev->limits.max_db_bits = SNB_MAX_DB_BITS;
ndev->reg_ofs.rdb = ndev->reg_base + SNB_PDOORBELL_OFFSET;
ndev->reg_ofs.ldb = ndev->reg_base + SNB_SDOORBELL_OFFSET;
ndev->reg_ofs.ldb_mask = ndev->reg_base + SNB_SDBMSK_OFFSET;
Expand All @@ -819,7 +865,6 @@ static int ntb_xeon_setup(struct ntb_device *ndev)
ndev->reg_ofs.lnk_stat = ndev->reg_base + SNB_SLINK_STATUS_OFFSET;
ndev->reg_ofs.spci_cmd = ndev->reg_base + SNB_PCICMD_OFFSET;

ndev->limits.max_db_bits = SNB_MAX_DB_BITS;
ndev->limits.msix_cnt = SNB_MSIX_CNT;
ndev->bits_per_vector = SNB_DB_BITS_PER_VEC;

Expand Down Expand Up @@ -934,12 +979,16 @@ static irqreturn_t bwd_callback_msix_irq(int irq, void *data)
{
struct ntb_db_cb *db_cb = data;
struct ntb_device *ndev = db_cb->ndev;
unsigned long mask;

dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq,
db_cb->db_num);

if (db_cb->callback)
db_cb->callback(db_cb->data, db_cb->db_num);
mask = readw(ndev->reg_ofs.ldb_mask);
set_bit(db_cb->db_num * ndev->bits_per_vector, &mask);
writew(mask, ndev->reg_ofs.ldb_mask);

tasklet_schedule(&db_cb->irq_work);

/* No need to check for the specific HB irq, any interrupt means
* we're connected.
Expand All @@ -955,12 +1004,16 @@ static irqreturn_t xeon_callback_msix_irq(int irq, void *data)
{
struct ntb_db_cb *db_cb = data;
struct ntb_device *ndev = db_cb->ndev;
unsigned long mask;

dev_dbg(&ndev->pdev->dev, "MSI-X irq %d received for DB %d\n", irq,
db_cb->db_num);

if (db_cb->callback)
db_cb->callback(db_cb->data, db_cb->db_num);
mask = readw(ndev->reg_ofs.ldb_mask);
set_bit(db_cb->db_num * ndev->bits_per_vector, &mask);
writew(mask, ndev->reg_ofs.ldb_mask);

tasklet_schedule(&db_cb->irq_work);

/* On Sandybridge, there are 16 bits in the interrupt register
* but only 4 vectors. So, 5 bits are assigned to the first 3
Expand All @@ -986,7 +1039,7 @@ static irqreturn_t xeon_event_msix_irq(int irq, void *dev)
dev_err(&ndev->pdev->dev, "Error determining link status\n");

/* bit 15 is always the link bit */
writew(1 << ndev->limits.max_db_bits, ndev->reg_ofs.ldb);
writew(1 << SNB_LINK_DB, ndev->reg_ofs.ldb);

return IRQ_HANDLED;
}
Expand Down Expand Up @@ -1075,6 +1128,10 @@ static int ntb_setup_msix(struct ntb_device *ndev)
"Only %d MSI-X vectors. Limiting the number of queues to that number.\n",
rc);
msix_entries = rc;

rc = pci_enable_msix(pdev, ndev->msix_entries, msix_entries);
if (rc)
goto err1;
}

for (i = 0; i < msix_entries; i++) {
Expand Down Expand Up @@ -1176,9 +1233,10 @@ static int ntb_setup_interrupts(struct ntb_device *ndev)
*/
if (ndev->hw_type == BWD_HW)
writeq(~0, ndev->reg_ofs.ldb_mask);
else
writew(~(1 << ndev->limits.max_db_bits),
ndev->reg_ofs.ldb_mask);
else {
u16 var = 1 << SNB_LINK_DB;
writew(~var, ndev->reg_ofs.ldb_mask);
}

rc = ntb_setup_msix(ndev);
if (!rc)
Expand Down Expand Up @@ -1286,6 +1344,39 @@ static void ntb_free_debugfs(struct ntb_device *ndev)
}
}

static void ntb_hw_link_up(struct ntb_device *ndev)
{
if (ndev->conn_type == NTB_CONN_TRANSPARENT)
ntb_link_event(ndev, NTB_LINK_UP);
else {
u32 ntb_cntl;

/* Let's bring the NTB link up */
ntb_cntl = readl(ndev->reg_ofs.lnk_cntl);
ntb_cntl &= ~(NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK);
ntb_cntl |= NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP;
ntb_cntl |= NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP;
writel(ntb_cntl, ndev->reg_ofs.lnk_cntl);
}
}

static void ntb_hw_link_down(struct ntb_device *ndev)
{
u32 ntb_cntl;

if (ndev->conn_type == NTB_CONN_TRANSPARENT) {
ntb_link_event(ndev, NTB_LINK_DOWN);
return;
}

/* Bring NTB link down */
ntb_cntl = readl(ndev->reg_ofs.lnk_cntl);
ntb_cntl &= ~(NTB_CNTL_P2S_BAR23_SNOOP | NTB_CNTL_S2P_BAR23_SNOOP);
ntb_cntl &= ~(NTB_CNTL_P2S_BAR45_SNOOP | NTB_CNTL_S2P_BAR45_SNOOP);
ntb_cntl |= NTB_CNTL_LINK_DISABLE | NTB_CNTL_CFG_LOCK;
writel(ntb_cntl, ndev->reg_ofs.lnk_cntl);
}

static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct ntb_device *ndev;
Expand Down Expand Up @@ -1374,9 +1465,7 @@ static int ntb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
goto err6;

/* Let's bring the NTB link up */
writel(NTB_CNTL_BAR23_SNOOP | NTB_CNTL_BAR45_SNOOP,
ndev->reg_ofs.lnk_cntl);
ntb_hw_link_up(ndev);

return 0;

Expand Down Expand Up @@ -1406,12 +1495,8 @@ static void ntb_pci_remove(struct pci_dev *pdev)
{
struct ntb_device *ndev = pci_get_drvdata(pdev);
int i;
u32 ntb_cntl;

/* Bring NTB link down */
ntb_cntl = readl(ndev->reg_ofs.lnk_cntl);
ntb_cntl |= NTB_CNTL_LINK_DISABLE;
writel(ntb_cntl, ndev->reg_ofs.lnk_cntl);
ntb_hw_link_down(ndev);

ntb_transport_free(ndev->ntb_transport);

Expand Down
7 changes: 4 additions & 3 deletions drivers/ntb/ntb_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,11 @@ struct ntb_mw {
};

struct ntb_db_cb {
void (*callback) (void *data, int db_num);
int (*callback)(void *data, int db_num);
unsigned int db_num;
void *data;
struct ntb_device *ndev;
struct tasklet_struct irq_work;
};

struct ntb_device {
Expand Down Expand Up @@ -228,8 +229,8 @@ struct ntb_device *ntb_register_transport(struct pci_dev *pdev,
void ntb_unregister_transport(struct ntb_device *ndev);
void ntb_set_mw_addr(struct ntb_device *ndev, unsigned int mw, u64 addr);
int ntb_register_db_callback(struct ntb_device *ndev, unsigned int idx,
void *data, void (*db_cb_func) (void *data,
int db_num));
void *data, int (*db_cb_func)(void *data,
int db_num));
void ntb_unregister_db_callback(struct ntb_device *ndev, unsigned int idx);
int ntb_register_event_callback(struct ntb_device *ndev,
void (*event_cb_func) (void *handle,
Expand Down
16 changes: 8 additions & 8 deletions drivers/ntb/ntb_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#define SNB_MAX_COMPAT_SPADS 16
/* Reserve the uppermost bit for link interrupt */
#define SNB_MAX_DB_BITS 15
#define SNB_LINK_DB 15
#define SNB_DB_BITS_PER_VEC 5
#define SNB_MAX_MW 2
#define SNB_ERRATA_MAX_MW 1
Expand All @@ -75,9 +76,6 @@
#define SNB_SBAR2XLAT_OFFSET 0x0030
#define SNB_SBAR4XLAT_OFFSET 0x0038
#define SNB_SBAR0BASE_OFFSET 0x0040
#define SNB_SBAR0BASE_OFFSET 0x0040
#define SNB_SBAR2BASE_OFFSET 0x0048
#define SNB_SBAR4BASE_OFFSET 0x0050
#define SNB_SBAR2BASE_OFFSET 0x0048
#define SNB_SBAR4BASE_OFFSET 0x0050
#define SNB_NTBCNTL_OFFSET 0x0058
Expand Down Expand Up @@ -145,11 +143,13 @@
#define BWD_LTSSMSTATEJMP_FORCEDETECT (1 << 2)
#define BWD_IBIST_ERR_OFLOW 0x7FFF7FFF

#define NTB_CNTL_CFG_LOCK (1 << 0)
#define NTB_CNTL_LINK_DISABLE (1 << 1)
#define NTB_CNTL_BAR23_SNOOP (1 << 2)
#define NTB_CNTL_BAR45_SNOOP (1 << 6)
#define BWD_CNTL_LINK_DOWN (1 << 16)
#define NTB_CNTL_CFG_LOCK (1 << 0)
#define NTB_CNTL_LINK_DISABLE (1 << 1)
#define NTB_CNTL_S2P_BAR23_SNOOP (1 << 2)
#define NTB_CNTL_P2S_BAR23_SNOOP (1 << 4)
#define NTB_CNTL_S2P_BAR45_SNOOP (1 << 6)
#define NTB_CNTL_P2S_BAR45_SNOOP (1 << 8)
#define BWD_CNTL_LINK_DOWN (1 << 16)

#define NTB_PPD_OFFSET 0x00D4
#define SNB_PPD_CONN_TYPE 0x0003
Expand Down
Loading

0 comments on commit b954851

Please sign in to comment.