mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
Merge branch 'pci/endpoint/epf-vntb'
- Return -ENOENT (not -1) if pci_epc_get_next_free_bar() fails (Jerome Brunet) - Align MW (memory window) naming with config names (Jerome Brunet) - Allow BAR assignment via configfs so platforms have flexibility in determining BAR usage (Jerome Brunet) - Drop incorrect '__iomem' annotation on the return value of pci_epf_alloc_space(); this also fixes an sparse warning (Manivannan Sadhasivam) * pci/endpoint/epf-vntb: PCI: endpoint: pci-epf-vntb: Fix the incorrect usage of __iomem attribute PCI: endpoint: pci-epf-vntb: Allow BAR assignment via configfs PCI: endpoint: pci-epf-vntb: Align MW naming with config names PCI: endpoint: pci-epf-vntb: Return -ENOENT if pci_epc_get_next_free_bar() fails
This commit is contained in:
commit
7f837a2648
1 changed files with 131 additions and 13 deletions
|
@ -70,9 +70,11 @@ static struct workqueue_struct *kpcintb_workqueue;
|
|||
enum epf_ntb_bar {
|
||||
BAR_CONFIG,
|
||||
BAR_DB,
|
||||
BAR_MW0,
|
||||
BAR_MW1,
|
||||
BAR_MW2,
|
||||
BAR_MW3,
|
||||
BAR_MW4,
|
||||
VNTB_BAR_NUM,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -132,7 +134,7 @@ struct epf_ntb {
|
|||
bool linkup;
|
||||
u32 spad_size;
|
||||
|
||||
enum pci_barno epf_ntb_bar[6];
|
||||
enum pci_barno epf_ntb_bar[VNTB_BAR_NUM];
|
||||
|
||||
struct epf_ntb_ctrl *reg;
|
||||
|
||||
|
@ -510,7 +512,7 @@ static int epf_ntb_db_bar_init(struct epf_ntb *ntb)
|
|||
struct device *dev = &ntb->epf->dev;
|
||||
int ret;
|
||||
struct pci_epf_bar *epf_bar;
|
||||
void __iomem *mw_addr;
|
||||
void *mw_addr;
|
||||
enum pci_barno barno;
|
||||
size_t size = sizeof(u32) * ntb->db_count;
|
||||
|
||||
|
@ -576,7 +578,7 @@ static int epf_ntb_mw_bar_init(struct epf_ntb *ntb)
|
|||
|
||||
for (i = 0; i < ntb->num_mws; i++) {
|
||||
size = ntb->mws_size[i];
|
||||
barno = ntb->epf_ntb_bar[BAR_MW0 + i];
|
||||
barno = ntb->epf_ntb_bar[BAR_MW1 + i];
|
||||
|
||||
ntb->epf->bar[barno].barno = barno;
|
||||
ntb->epf->bar[barno].size = size;
|
||||
|
@ -629,7 +631,7 @@ static void epf_ntb_mw_bar_clear(struct epf_ntb *ntb, int num_mws)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < num_mws; i++) {
|
||||
barno = ntb->epf_ntb_bar[BAR_MW0 + i];
|
||||
barno = ntb->epf_ntb_bar[BAR_MW1 + i];
|
||||
pci_epc_clear_bar(ntb->epf->epc,
|
||||
ntb->epf->func_no,
|
||||
ntb->epf->vfunc_no,
|
||||
|
@ -654,6 +656,63 @@ static void epf_ntb_epc_destroy(struct epf_ntb *ntb)
|
|||
pci_epc_put(ntb->epf->epc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* epf_ntb_is_bar_used() - Check if a bar is used in the ntb configuration
|
||||
* @ntb: NTB device that facilitates communication between HOST and VHOST
|
||||
* @barno: Checked bar number
|
||||
*
|
||||
* Returns: true if used, false if free.
|
||||
*/
|
||||
static bool epf_ntb_is_bar_used(struct epf_ntb *ntb,
|
||||
enum pci_barno barno)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < VNTB_BAR_NUM; i++) {
|
||||
if (ntb->epf_ntb_bar[i] == barno)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* epf_ntb_find_bar() - Assign BAR number when no configuration is provided
|
||||
* @ntb: NTB device that facilitates communication between HOST and VHOST
|
||||
* @epc_features: The features provided by the EPC specific to this EPF
|
||||
* @bar: NTB BAR index
|
||||
* @barno: Bar start index
|
||||
*
|
||||
* When the BAR configuration was not provided through the userspace
|
||||
* configuration, automatically assign BAR as it has been historically
|
||||
* done by this endpoint function.
|
||||
*
|
||||
* Returns: the BAR number found, if any. -1 otherwise
|
||||
*/
|
||||
static int epf_ntb_find_bar(struct epf_ntb *ntb,
|
||||
const struct pci_epc_features *epc_features,
|
||||
enum epf_ntb_bar bar,
|
||||
enum pci_barno barno)
|
||||
{
|
||||
while (ntb->epf_ntb_bar[bar] < 0) {
|
||||
barno = pci_epc_get_next_free_bar(epc_features, barno);
|
||||
if (barno < 0)
|
||||
break; /* No more BAR available */
|
||||
|
||||
/*
|
||||
* Verify if the BAR found is not already assigned
|
||||
* through the provided configuration
|
||||
*/
|
||||
if (!epf_ntb_is_bar_used(ntb, barno))
|
||||
ntb->epf_ntb_bar[bar] = barno;
|
||||
|
||||
barno += 1;
|
||||
}
|
||||
|
||||
return barno;
|
||||
}
|
||||
|
||||
/**
|
||||
* epf_ntb_init_epc_bar() - Identify BARs to be used for each of the NTB
|
||||
* constructs (scratchpad region, doorbell, memorywindow)
|
||||
|
@ -676,23 +735,21 @@ static int epf_ntb_init_epc_bar(struct epf_ntb *ntb)
|
|||
epc_features = pci_epc_get_features(ntb->epf->epc, ntb->epf->func_no, ntb->epf->vfunc_no);
|
||||
|
||||
/* These are required BARs which are mandatory for NTB functionality */
|
||||
for (bar = BAR_CONFIG; bar <= BAR_MW0; bar++, barno++) {
|
||||
barno = pci_epc_get_next_free_bar(epc_features, barno);
|
||||
for (bar = BAR_CONFIG; bar <= BAR_MW1; bar++) {
|
||||
barno = epf_ntb_find_bar(ntb, epc_features, bar, barno);
|
||||
if (barno < 0) {
|
||||
dev_err(dev, "Fail to get NTB function BAR\n");
|
||||
return barno;
|
||||
return -ENOENT;
|
||||
}
|
||||
ntb->epf_ntb_bar[bar] = barno;
|
||||
}
|
||||
|
||||
/* These are optional BARs which don't impact NTB functionality */
|
||||
for (bar = BAR_MW1, i = 1; i < num_mws; bar++, barno++, i++) {
|
||||
barno = pci_epc_get_next_free_bar(epc_features, barno);
|
||||
for (bar = BAR_MW1, i = 1; i < num_mws; bar++, i++) {
|
||||
barno = epf_ntb_find_bar(ntb, epc_features, bar, barno);
|
||||
if (barno < 0) {
|
||||
ntb->num_mws = i;
|
||||
dev_dbg(dev, "BAR not available for > MW%d\n", i + 1);
|
||||
}
|
||||
ntb->epf_ntb_bar[bar] = barno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -860,6 +917,37 @@ static ssize_t epf_ntb_##_name##_store(struct config_item *item, \
|
|||
return len; \
|
||||
}
|
||||
|
||||
#define EPF_NTB_BAR_R(_name, _id) \
|
||||
static ssize_t epf_ntb_##_name##_show(struct config_item *item, \
|
||||
char *page) \
|
||||
{ \
|
||||
struct config_group *group = to_config_group(item); \
|
||||
struct epf_ntb *ntb = to_epf_ntb(group); \
|
||||
\
|
||||
return sprintf(page, "%d\n", ntb->epf_ntb_bar[_id]); \
|
||||
}
|
||||
|
||||
#define EPF_NTB_BAR_W(_name, _id) \
|
||||
static ssize_t epf_ntb_##_name##_store(struct config_item *item, \
|
||||
const char *page, size_t len) \
|
||||
{ \
|
||||
struct config_group *group = to_config_group(item); \
|
||||
struct epf_ntb *ntb = to_epf_ntb(group); \
|
||||
int val; \
|
||||
int ret; \
|
||||
\
|
||||
ret = kstrtoint(page, 0, &val); \
|
||||
if (ret) \
|
||||
return ret; \
|
||||
\
|
||||
if (val < NO_BAR || val > BAR_5) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
ntb->epf_ntb_bar[_id] = val; \
|
||||
\
|
||||
return len; \
|
||||
}
|
||||
|
||||
static ssize_t epf_ntb_num_mws_store(struct config_item *item,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
|
@ -899,6 +987,18 @@ EPF_NTB_MW_R(mw3)
|
|||
EPF_NTB_MW_W(mw3)
|
||||
EPF_NTB_MW_R(mw4)
|
||||
EPF_NTB_MW_W(mw4)
|
||||
EPF_NTB_BAR_R(ctrl_bar, BAR_CONFIG)
|
||||
EPF_NTB_BAR_W(ctrl_bar, BAR_CONFIG)
|
||||
EPF_NTB_BAR_R(db_bar, BAR_DB)
|
||||
EPF_NTB_BAR_W(db_bar, BAR_DB)
|
||||
EPF_NTB_BAR_R(mw1_bar, BAR_MW1)
|
||||
EPF_NTB_BAR_W(mw1_bar, BAR_MW1)
|
||||
EPF_NTB_BAR_R(mw2_bar, BAR_MW2)
|
||||
EPF_NTB_BAR_W(mw2_bar, BAR_MW2)
|
||||
EPF_NTB_BAR_R(mw3_bar, BAR_MW3)
|
||||
EPF_NTB_BAR_W(mw3_bar, BAR_MW3)
|
||||
EPF_NTB_BAR_R(mw4_bar, BAR_MW4)
|
||||
EPF_NTB_BAR_W(mw4_bar, BAR_MW4)
|
||||
|
||||
CONFIGFS_ATTR(epf_ntb_, spad_count);
|
||||
CONFIGFS_ATTR(epf_ntb_, db_count);
|
||||
|
@ -910,6 +1010,12 @@ CONFIGFS_ATTR(epf_ntb_, mw4);
|
|||
CONFIGFS_ATTR(epf_ntb_, vbus_number);
|
||||
CONFIGFS_ATTR(epf_ntb_, vntb_pid);
|
||||
CONFIGFS_ATTR(epf_ntb_, vntb_vid);
|
||||
CONFIGFS_ATTR(epf_ntb_, ctrl_bar);
|
||||
CONFIGFS_ATTR(epf_ntb_, db_bar);
|
||||
CONFIGFS_ATTR(epf_ntb_, mw1_bar);
|
||||
CONFIGFS_ATTR(epf_ntb_, mw2_bar);
|
||||
CONFIGFS_ATTR(epf_ntb_, mw3_bar);
|
||||
CONFIGFS_ATTR(epf_ntb_, mw4_bar);
|
||||
|
||||
static struct configfs_attribute *epf_ntb_attrs[] = {
|
||||
&epf_ntb_attr_spad_count,
|
||||
|
@ -922,6 +1028,12 @@ static struct configfs_attribute *epf_ntb_attrs[] = {
|
|||
&epf_ntb_attr_vbus_number,
|
||||
&epf_ntb_attr_vntb_pid,
|
||||
&epf_ntb_attr_vntb_vid,
|
||||
&epf_ntb_attr_ctrl_bar,
|
||||
&epf_ntb_attr_db_bar,
|
||||
&epf_ntb_attr_mw1_bar,
|
||||
&epf_ntb_attr_mw2_bar,
|
||||
&epf_ntb_attr_mw3_bar,
|
||||
&epf_ntb_attr_mw4_bar,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -1048,7 +1160,7 @@ static int vntb_epf_mw_set_trans(struct ntb_dev *ndev, int pidx, int idx,
|
|||
struct device *dev;
|
||||
|
||||
dev = &ntb->ntb.dev;
|
||||
barno = ntb->epf_ntb_bar[BAR_MW0 + idx];
|
||||
barno = ntb->epf_ntb_bar[BAR_MW1 + idx];
|
||||
epf_bar = &ntb->epf->bar[barno];
|
||||
epf_bar->phys_addr = addr;
|
||||
epf_bar->barno = barno;
|
||||
|
@ -1379,6 +1491,7 @@ static int epf_ntb_probe(struct pci_epf *epf,
|
|||
{
|
||||
struct epf_ntb *ntb;
|
||||
struct device *dev;
|
||||
int i;
|
||||
|
||||
dev = &epf->dev;
|
||||
|
||||
|
@ -1389,6 +1502,11 @@ static int epf_ntb_probe(struct pci_epf *epf,
|
|||
epf->header = &epf_ntb_header;
|
||||
ntb->epf = epf;
|
||||
ntb->vbus_number = 0xff;
|
||||
|
||||
/* Initially, no bar is assigned */
|
||||
for (i = 0; i < VNTB_BAR_NUM; i++)
|
||||
ntb->epf_ntb_bar[i] = NO_BAR;
|
||||
|
||||
epf_set_drvdata(epf, ntb);
|
||||
|
||||
dev_info(dev, "pci-ep epf driver loaded\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue