NTB: MFV 113fc505: Handle 64bit BAR sizes

64bit BAR sizes are permissible with an NTB device.  To support them
various modifications and clean-ups were required, most significantly
using 2 32bit scratch pad registers for each BAR.

Also, modify the driver to allow more than 2 Memory Windows.

Authored by:	Jon Mason
Obtained from:	Linux
Sponsored by:	EMC / Isilon Storage Division
This commit is contained in:
cem 2015-10-11 20:58:00 +00:00
parent 78020bdbae
commit 393effa336

View File

@ -194,11 +194,22 @@ struct ntb_payload_header {
};
enum {
/*
* The order of this enum is part of the if_ntb remote protocol. Do
* not reorder without bumping protocol version (and it's probably best
* to keep the protocol in lock-step with the Linux NTB driver.
*/
IF_NTB_VERSION = 0,
IF_NTB_MW0_SZ,
IF_NTB_MW1_SZ,
IF_NTB_NUM_QPS,
IF_NTB_QP_LINKS,
IF_NTB_NUM_QPS,
IF_NTB_NUM_MWS,
/*
* N.B.: transport_link_work assumes MW1 enums = MW0 + 2.
*/
IF_NTB_MW0_SZ_HIGH,
IF_NTB_MW0_SZ_LOW,
IF_NTB_MW1_SZ_HIGH,
IF_NTB_MW1_SZ_LOW,
IF_NTB_MAX_SPAD,
};
@ -242,6 +253,7 @@ static void ntb_rx_completion_task(void *arg, int pending);
static void ntb_transport_event_callback(void *data, enum ntb_hw_event event);
static void ntb_transport_link_work(void *arg);
static int ntb_set_mw(struct ntb_netdev *nt, int num_mw, unsigned int size);
static void ntb_free_mw(struct ntb_netdev *nt, int num_mw);
static void ntb_transport_setup_qp_mw(struct ntb_netdev *nt,
unsigned int qp_num);
static void ntb_qp_link_work(void *arg);
@ -514,9 +526,7 @@ ntb_transport_free(void *transport)
ntb_unregister_event_callback(ntb);
for (i = 0; i < NTB_NUM_MW; i++)
if (nt->mw[i].virt_addr != NULL)
contigfree(nt->mw[i].virt_addr, nt->mw[i].size,
M_NTB_IF);
ntb_free_mw(nt, i);
free(nt->qps, M_NTB_IF);
ntb_unregister_transport(ntb);
@ -1019,19 +1029,24 @@ ntb_transport_link_work(void *arg)
struct ntb_netdev *nt = arg;
struct ntb_softc *ntb = nt->ntb;
struct ntb_transport_qp *qp;
uint64_t val64;
uint32_t val;
int rc, i;
/* send the local info */
rc = ntb_write_remote_spad(ntb, IF_NTB_VERSION, NTB_TRANSPORT_VERSION);
if (rc != 0)
goto out;
/* send the local info, in the opposite order of the way we read it */
for (i = 0; i < NTB_NUM_MW; i++) {
rc = ntb_write_remote_spad(ntb, IF_NTB_MW0_SZ_HIGH + (i * 2),
ntb_get_mw_size(ntb, i) >> 32);
if (rc != 0)
goto out;
rc = ntb_write_remote_spad(ntb, IF_NTB_MW0_SZ, ntb_get_mw_size(ntb, 0));
if (rc != 0)
goto out;
rc = ntb_write_remote_spad(ntb, IF_NTB_MW0_SZ_LOW + (i * 2),
(uint32_t)ntb_get_mw_size(ntb, i));
if (rc != 0)
goto out;
}
rc = ntb_write_remote_spad(ntb, IF_NTB_MW1_SZ, ntb_get_mw_size(ntb, 1));
rc = ntb_write_remote_spad(ntb, IF_NTB_NUM_MWS, NTB_NUM_MW);
if (rc != 0)
goto out;
@ -1039,11 +1054,7 @@ ntb_transport_link_work(void *arg)
if (rc != 0)
goto out;
rc = ntb_read_remote_spad(ntb, IF_NTB_QP_LINKS, &val);
if (rc != 0)
goto out;
rc = ntb_write_remote_spad(ntb, IF_NTB_QP_LINKS, val);
rc = ntb_write_remote_spad(ntb, IF_NTB_VERSION, NTB_TRANSPORT_VERSION);
if (rc != 0)
goto out;
@ -1062,27 +1073,32 @@ ntb_transport_link_work(void *arg)
if (val != nt->max_qps)
goto out;
rc = ntb_read_local_spad(ntb, IF_NTB_MW0_SZ, &val);
rc = ntb_read_local_spad(ntb, IF_NTB_NUM_MWS, &val);
if (rc != 0)
goto out;
if (val == 0)
if (val != NTB_NUM_MW)
goto out;
rc = ntb_set_mw(nt, 0, val);
if (rc != 0)
return;
for (i = 0; i < NTB_NUM_MW; i++) {
rc = ntb_read_local_spad(ntb, IF_NTB_MW0_SZ_HIGH + (i * 2),
&val);
if (rc != 0)
goto free_mws;
rc = ntb_read_local_spad(ntb, IF_NTB_MW1_SZ, &val);
if (rc != 0)
goto out;
val64 = (uint64_t)val << 32;
if (val == 0)
goto out;
rc = ntb_read_local_spad(ntb, IF_NTB_MW0_SZ_LOW + (i * 2),
&val);
if (rc != 0)
goto free_mws;
rc = ntb_set_mw(nt, 1, val);
if (rc != 0)
return;
val64 |= val;
rc = ntb_set_mw(nt, i, val64);
if (rc != 0)
goto free_mws;
}
nt->transport_link = NTB_LINK_UP;
if (bootverbose)
@ -1099,10 +1115,13 @@ ntb_transport_link_work(void *arg)
return;
free_mws:
for (i = 0; i < NTB_NUM_MW; i++)
ntb_free_mw(nt, i);
out:
if (ntb_query_link_status(ntb))
callout_reset(&nt->link_work,
NTB_LINK_DOWN_TIMEOUT * hz / 1000, ntb_transport_link_work, nt);
NTB_LINK_DOWN_TIMEOUT * hz / 1000, ntb_transport_link_work, nt);
}
static int
@ -1129,6 +1148,18 @@ ntb_set_mw(struct ntb_netdev *nt, int num_mw, unsigned int size)
return (0);
}
static void
ntb_free_mw(struct ntb_netdev *nt, int num_mw)
{
struct ntb_transport_mw *mw = &nt->mw[num_mw];
if (mw->virt_addr == NULL)
return;
contigfree(mw->virt_addr, mw->size, M_NTB_IF);
mw->virt_addr = NULL;
}
static void
ntb_transport_setup_qp_mw(struct ntb_netdev *nt, unsigned int qp_num)
{