Skip to content

Commit

Permalink
Merge branch 'cxgb4-next'
Browse files Browse the repository at this point in the history
Hariprasad Shenai says:

====================
cxgb4: Fix for PCI passthrough and some Misc. fixes

This patch series fixes probe failure in VM when PF is exposed through PCI
Passthrough. Adds support to use firmware interface to get BAR0 value.
Replace the backdoor mechanism to access the HW memory with PCIe Window method
which fixes memory I/O. Also adds device ID of few more adapters for cxgb4 and
cxgb4vf driver.

The patches series is created against 'net-next' tree.
And includes patches on cxgb4, cxgb4vf and iw_cxgb4 driver.

Since this patch-series contains mainly cxgb4 related changes, we would like to
request this patch series to get merged via David Miller's 'net-next' tree.

We have included all the maintainers of respective drivers. Kindly review the
change and let us know in case of any review comments.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 2, 2014
2 parents 2eb27a1 + dde3aad commit 813f8e2
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 189 deletions.
3 changes: 2 additions & 1 deletion drivers/infiniband/hw/cxgb4/cm.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,8 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
16)) | FW_WR_FLOWID(ep->hwtid));

flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
flowc->mnemval[0].val = cpu_to_be32(PCI_FUNC(ep->com.dev->rdev.lldi.pdev->devfn) << 8);
flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN
(ep->com.dev->rdev.lldi.pf));
flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan);
flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
Expand Down
20 changes: 16 additions & 4 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ enum {
MEMWIN1_BASE_T5 = 0x52000,
MEMWIN2_APERTURE = 65536,
MEMWIN2_BASE = 0x30000,
MEMWIN2_BASE_T5 = 0x54000,
MEMWIN2_APERTURE_T5 = 131072,
MEMWIN2_BASE_T5 = 0x60000,
};

enum dev_master {
Expand Down Expand Up @@ -608,6 +609,7 @@ struct l2t_data;
struct adapter {
void __iomem *regs;
void __iomem *bar2;
u32 t4_bar0;
struct pci_dev *pdev;
struct device *pdev_dev;
unsigned int mbox;
Expand Down Expand Up @@ -652,6 +654,7 @@ struct adapter {
struct dentry *debugfs_root;

spinlock_t stats_lock;
spinlock_t win0_lock ____cacheline_aligned_in_smp;
};

/* Defined bit width of user definable filter tuples
Expand Down Expand Up @@ -946,6 +949,7 @@ void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
unsigned int data_reg, u32 *vals, unsigned int nregs,
unsigned int start_idx);
void t4_hw_pci_read_cfg4(struct adapter *adapter, int reg, u32 *val);

struct fw_filter_wr;

Expand All @@ -957,8 +961,17 @@ int t4_wait_dev_ready(struct adapter *adap);
int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port,
struct link_config *lc);
int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port);
int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
__be32 *buf);

#define T4_MEMORY_WRITE 0
#define T4_MEMORY_READ 1
int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr, u32 len,
__be32 *buf, int dir);
static inline int t4_memory_write(struct adapter *adap, int mtype, u32 addr,
u32 len, __be32 *buf)
{
return t4_memory_rw(adap, 0, mtype, addr, len, buf, 0);
}

int t4_seeprom_wp(struct adapter *adapter, bool enable);
int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
Expand Down Expand Up @@ -1056,7 +1069,6 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
void t4_db_full(struct adapter *adapter);
void t4_db_dropped(struct adapter *adapter);
int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len);
int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
u32 addr, u32 val);
void t4_sge_decode_idma_state(struct adapter *adapter, int state);
Expand Down
168 changes: 126 additions & 42 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,17 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
CH_DEVICE(0x4008, -1),
CH_DEVICE(0x4009, -1),
CH_DEVICE(0x400a, -1),
CH_DEVICE(0x400d, -1),
CH_DEVICE(0x400e, -1),
CH_DEVICE(0x4080, -1),
CH_DEVICE(0x4081, -1),
CH_DEVICE(0x4082, -1),
CH_DEVICE(0x4083, -1),
CH_DEVICE(0x4084, -1),
CH_DEVICE(0x4085, -1),
CH_DEVICE(0x4086, -1),
CH_DEVICE(0x4087, -1),
CH_DEVICE(0x4088, -1),
CH_DEVICE(0x4401, 4),
CH_DEVICE(0x4402, 4),
CH_DEVICE(0x4403, 4),
Expand All @@ -236,6 +247,15 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
CH_DEVICE(0x440a, 4),
CH_DEVICE(0x440d, 4),
CH_DEVICE(0x440e, 4),
CH_DEVICE(0x4480, 4),
CH_DEVICE(0x4481, 4),
CH_DEVICE(0x4482, 4),
CH_DEVICE(0x4483, 4),
CH_DEVICE(0x4484, 4),
CH_DEVICE(0x4485, 4),
CH_DEVICE(0x4486, 4),
CH_DEVICE(0x4487, 4),
CH_DEVICE(0x4488, 4),
CH_DEVICE(0x5001, 4),
CH_DEVICE(0x5002, 4),
CH_DEVICE(0x5003, 4),
Expand Down Expand Up @@ -3066,6 +3086,8 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
loff_t avail = file_inode(file)->i_size;
unsigned int mem = (uintptr_t)file->private_data & 3;
struct adapter *adap = file->private_data - mem;
__be32 *data;
int ret;

if (pos < 0)
return -EINVAL;
Expand All @@ -3074,29 +3096,24 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
if (count > avail - pos)
count = avail - pos;

while (count) {
size_t len;
int ret, ofst;
__be32 data[16];
data = t4_alloc_mem(count);
if (!data)
return -ENOMEM;

if ((mem == MEM_MC) || (mem == MEM_MC1))
ret = t4_mc_read(adap, mem % MEM_MC, pos, data, NULL);
else
ret = t4_edc_read(adap, mem, pos, data, NULL);
if (ret)
return ret;
spin_lock(&adap->win0_lock);
ret = t4_memory_rw(adap, 0, mem, pos, count, data, T4_MEMORY_READ);
spin_unlock(&adap->win0_lock);
if (ret) {
t4_free_mem(data);
return ret;
}
ret = copy_to_user(buf, data, count);

ofst = pos % sizeof(data);
len = min(count, sizeof(data) - ofst);
if (copy_to_user(buf, (u8 *)data + ofst, len))
return -EFAULT;
t4_free_mem(data);
if (ret)
return -EFAULT;

buf += len;
pos += len;
count -= len;
}
count = pos - *ppos;
*ppos = pos;
*ppos = pos + count;
return count;
}

Expand Down Expand Up @@ -3757,7 +3774,11 @@ static int read_eq_indices(struct adapter *adap, u16 qid, u16 *pidx, u16 *cidx)
__be64 indices;
int ret;

ret = t4_mem_win_read_len(adap, addr, (__be32 *)&indices, 8);
spin_lock(&adap->win0_lock);
ret = t4_memory_rw(adap, 0, MEM_EDC0, addr,
sizeof(indices), (__be32 *)&indices,
T4_MEMORY_READ);
spin_unlock(&adap->win0_lock);
if (!ret) {
*cidx = (be64_to_cpu(indices) >> 25) & 0xffff;
*pidx = (be64_to_cpu(indices) >> 9) & 0xffff;
Expand Down Expand Up @@ -4053,6 +4074,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
unsigned short i;

lli.pdev = adap->pdev;
lli.pf = adap->fn;
lli.l2t = adap->l2t;
lli.tids = &adap->tids;
lli.ports = adap->port;
Expand Down Expand Up @@ -4772,20 +4794,75 @@ void t4_fatal_err(struct adapter *adap)
dev_alert(adap->pdev_dev, "encountered fatal error, adapter stopped\n");
}

/* Return the specified PCI-E Configuration Space register from our Physical
* Function. We try first via a Firmware LDST Command since we prefer to let
* the firmware own all of these registers, but if that fails we go for it
* directly ourselves.
*/
static u32 t4_read_pcie_cfg4(struct adapter *adap, int reg)
{
struct fw_ldst_cmd ldst_cmd;
u32 val;
int ret;

/* Construct and send the Firmware LDST Command to retrieve the
* specified PCI-E Configuration Space register.
*/
memset(&ldst_cmd, 0, sizeof(ldst_cmd));
ldst_cmd.op_to_addrspace =
htonl(FW_CMD_OP(FW_LDST_CMD) |
FW_CMD_REQUEST |
FW_CMD_READ |
FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE));
ldst_cmd.cycles_to_len16 = htonl(FW_LEN16(ldst_cmd));
ldst_cmd.u.pcie.select_naccess = FW_LDST_CMD_NACCESS(1);
ldst_cmd.u.pcie.ctrl_to_fn =
(FW_LDST_CMD_LC | FW_LDST_CMD_FN(adap->fn));
ldst_cmd.u.pcie.r = reg;
ret = t4_wr_mbox(adap, adap->mbox, &ldst_cmd, sizeof(ldst_cmd),
&ldst_cmd);

/* If the LDST Command suucceeded, exctract the returned register
* value. Otherwise read it directly ourself.
*/
if (ret == 0)
val = ntohl(ldst_cmd.u.pcie.data[0]);
else
t4_hw_pci_read_cfg4(adap, reg, &val);

return val;
}

static void setup_memwin(struct adapter *adap)
{
u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base;
u32 mem_win0_base, mem_win1_base, mem_win2_base, mem_win2_aperture;

bar0 = pci_resource_start(adap->pdev, 0); /* truncation intentional */
if (is_t4(adap->params.chip)) {
u32 bar0;

/* Truncation intentional: we only read the bottom 32-bits of
* the 64-bit BAR0/BAR1 ... We use the hardware backdoor
* mechanism to read BAR0 instead of using
* pci_resource_start() because we could be operating from
* within a Virtual Machine which is trapping our accesses to
* our Configuration Space and we need to set up the PCI-E
* Memory Window decoders with the actual addresses which will
* be coming across the PCI-E link.
*/
bar0 = t4_read_pcie_cfg4(adap, PCI_BASE_ADDRESS_0);
bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
adap->t4_bar0 = bar0;

mem_win0_base = bar0 + MEMWIN0_BASE;
mem_win1_base = bar0 + MEMWIN1_BASE;
mem_win2_base = bar0 + MEMWIN2_BASE;
mem_win2_aperture = MEMWIN2_APERTURE;
} else {
/* For T5, only relative offset inside the PCIe BAR is passed */
mem_win0_base = MEMWIN0_BASE;
mem_win1_base = MEMWIN1_BASE_T5;
mem_win1_base = MEMWIN1_BASE;
mem_win2_base = MEMWIN2_BASE_T5;
mem_win2_aperture = MEMWIN2_APERTURE_T5;
}
t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0),
mem_win0_base | BIR(0) |
Expand All @@ -4795,16 +4872,19 @@ static void setup_memwin(struct adapter *adap)
WINDOW(ilog2(MEMWIN1_APERTURE) - 10));
t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2),
mem_win2_base | BIR(0) |
WINDOW(ilog2(MEMWIN2_APERTURE) - 10));
WINDOW(ilog2(mem_win2_aperture) - 10));
t4_read_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
}

static void setup_memwin_rdma(struct adapter *adap)
{
if (adap->vres.ocq.size) {
unsigned int start, sz_kb;
u32 start;
unsigned int sz_kb;

start = pci_resource_start(adap->pdev, 2) +
OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
start = t4_read_pcie_cfg4(adap, PCI_BASE_ADDRESS_2);
start &= PCI_BASE_ADDRESS_MEM_MASK;
start += OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
sz_kb = roundup_pow_of_two(adap->vres.ocq.size) >> 10;
t4_write_reg(adap,
PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 3),
Expand Down Expand Up @@ -5017,7 +5097,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
adapter->fn, 0, 1, params, val);
if (ret == 0) {
/*
* For t4_memory_write() below addresses and
* For t4_memory_rw() below addresses and
* sizes have to be in terms of multiples of 4
* bytes. So, if the Configuration File isn't
* a multiple of 4 bytes in length we'll have
Expand All @@ -5033,8 +5113,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
mtype = FW_PARAMS_PARAM_Y_GET(val[0]);
maddr = FW_PARAMS_PARAM_Z_GET(val[0]) << 16;

ret = t4_memory_write(adapter, mtype, maddr,
size, data);
spin_lock(&adapter->win0_lock);
ret = t4_memory_rw(adapter, 0, mtype, maddr,
size, data, T4_MEMORY_WRITE);
if (ret == 0 && resid != 0) {
union {
__be32 word;
Expand All @@ -5045,10 +5126,12 @@ static int adap_init0_config(struct adapter *adapter, int reset)
last.word = data[size >> 2];
for (i = resid; i < 4; i++)
last.buf[i] = 0;
ret = t4_memory_write(adapter, mtype,
maddr + size,
4, &last.word);
ret = t4_memory_rw(adapter, 0, mtype,
maddr + size,
4, &last.word,
T4_MEMORY_WRITE);
}
spin_unlock(&adapter->win0_lock);
}
}

Expand Down Expand Up @@ -6294,13 +6377,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
}

/* We control everything through one PF */
func = PCI_FUNC(pdev->devfn);
if (func != ent->driver_data) {
pci_save_state(pdev); /* to restore SR-IOV later */
goto sriov;
}

err = pci_enable_device(pdev);
if (err) {
dev_err(&pdev->dev, "cannot enable PCI device\n");
Expand Down Expand Up @@ -6344,6 +6420,15 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_free_adapter;
}

/* We control everything through one PF */
func = SOURCEPF_GET(readl(adapter->regs + PL_WHOAMI));
if ((pdev->device == 0xa000 && func != 0) ||
func != ent->driver_data) {
pci_save_state(pdev); /* to restore SR-IOV later */
err = 0;
goto out_unmap_bar0;
}

adapter->pdev = pdev;
adapter->pdev_dev = &pdev->dev;
adapter->mbox = func;
Expand Down Expand Up @@ -6507,7 +6592,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (is_offload(adapter))
attach_ulds(adapter);

sriov:
#ifdef CONFIG_PCI_IOV
if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0)
if (pci_enable_sriov(pdev, num_vf[func]) == 0)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ struct cxgb4_lld_info {
int dbfifo_int_thresh; /* doorbell fifo int threshold */
unsigned int sge_pktshift; /* Padding between CPL and */
/* packet data */
unsigned int pf; /* Physical Function we're using */
bool enable_fw_ofld_conn; /* Enable connection through fw */
/* WR */
bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */
Expand Down
Loading

0 comments on commit 813f8e2

Please sign in to comment.