Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions linux/switchtec.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#define SWITCHTEC_EVENT_EN_IRQ BIT(3)
#define SWITCHTEC_EVENT_FATAL BIT(4)

#define SWITCHTEC_DMA_MRPC_EN BIT(0)
enum {
SWITCHTEC_GAS_MRPC_OFFSET = 0x0000,
SWITCHTEC_GAS_TOP_CFG_OFFSET = 0x1000,
Expand All @@ -50,6 +51,10 @@ struct mrpc_regs {
u32 cmd;
u32 status;
u32 ret_value;
u32 dma_en;
u64 dma_addr;
u32 dma_vector;
u32 dma_ver;
} __packed;

enum mrpc_status {
Expand Down Expand Up @@ -359,6 +364,14 @@ struct pff_csr_regs {

struct switchtec_ntb;

struct dma_mrpc_output{
u32 status;
u32 cmd_id;
u32 rtn_code;
u32 output_size;
u8 data[SWITCHTEC_MRPC_PAYLOAD_SIZE];
};

struct switchtec_dev {
struct pci_dev *pdev;
struct device dev;
Expand Down Expand Up @@ -398,6 +411,9 @@ struct switchtec_dev {
u8 link_event_count[SWITCHTEC_MAX_PFF_CSR];

struct switchtec_ntb *sndev;

struct dma_mrpc_output *dma_mrpc;
dma_addr_t dma_mrpc_dma_addr;
};

static inline struct switchtec_dev *to_stdev(struct device *dev)
Expand Down
97 changes: 88 additions & 9 deletions switchtec.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ static int max_devices = 16;
module_param(max_devices, int, 0644);
MODULE_PARM_DESC(max_devices, "max number of switchtec device instances");

static bool use_dma_mrpc = 1;
module_param(use_dma_mrpc, bool, 0644);
MODULE_PARM_DESC(use_dma_mrpc,
"Enable the use of the DMA MRPC feature");

static dev_t switchtec_devt;
static DEFINE_IDA(switchtec_minor_ida);

Expand Down Expand Up @@ -174,7 +179,11 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
list);

stuser->status = ioread32(&stdev->mmio_mrpc->status);
if (stdev->dma_mrpc)
stuser->status = stdev->dma_mrpc->status;
else
stuser->status = ioread32(&stdev->mmio_mrpc->status);

if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS)
return;

Expand All @@ -184,13 +193,19 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE)
goto out;

stuser->return_code = ioread32(&stdev->mmio_mrpc->ret_value);
if (stdev->dma_mrpc)
stuser->return_code = stdev->dma_mrpc->rtn_code;
else
stuser->return_code = ioread32(&stdev->mmio_mrpc->ret_value);
if (stuser->return_code != 0)
goto out;

memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data,
stuser->read_len);

if (stdev->dma_mrpc)
memcpy(stuser->data, &stdev->dma_mrpc->data,
stuser->read_len);
else
memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data,
stuser->read_len);
out:
complete_all(&stuser->comp);
list_del_init(&stuser->list);
Expand Down Expand Up @@ -225,15 +240,17 @@ static void mrpc_timeout_work(struct work_struct *work)

mutex_lock(&stdev->mrpc_mutex);

status = ioread32(&stdev->mmio_mrpc->status);
if (stdev->dma_mrpc)
status = stdev->dma_mrpc->status;
else
status = ioread32(&stdev->mmio_mrpc->status);
if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) {
schedule_delayed_work(&stdev->mrpc_timeout,
msecs_to_jiffies(500));
goto out;
}

mrpc_complete_cmd(stdev);

out:
mutex_unlock(&stdev->mrpc_mutex);
}
Expand Down Expand Up @@ -1019,10 +1036,22 @@ static void enable_link_state_events(struct switchtec_dev *stdev)
}
}

static void enable_dma_mrpc(struct switchtec_dev *stdev)
{
writeq(stdev->dma_mrpc_dma_addr, &stdev->mmio_mrpc->dma_addr);
iowrite32(SWITCHTEC_DMA_MRPC_EN, &stdev->mmio_mrpc->dma_en);
}

static void stdev_release(struct device *dev)
{
struct switchtec_dev *stdev = to_stdev(dev);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: a space should always come after the variables are declared.


if (stdev->dma_mrpc){
iowrite32(0, &stdev->mmio_mrpc->dma_en);
writeq(0, &stdev->mmio_mrpc->dma_addr);
dma_free_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc),
stdev->dma_mrpc, stdev->dma_mrpc_dma_addr);
}
kfree(stdev);
}

Expand Down Expand Up @@ -1178,10 +1207,27 @@ static irqreturn_t switchtec_event_isr(int irq, void *dev)
return ret;
}


static irqreturn_t switchtec_dma_mrpc_isr(int irq, void *dev)
{
struct switchtec_dev *stdev = dev;
irqreturn_t ret = IRQ_NONE;

iowrite32(SWITCHTEC_EVENT_CLEAR |
SWITCHTEC_EVENT_EN_IRQ,
&stdev->mmio_part_cfg->mrpc_comp_hdr);
schedule_work(&stdev->mrpc_work);

ret = IRQ_HANDLED;
return ret;
}

static int switchtec_init_isr(struct switchtec_dev *stdev)
{
int nvecs;
int event_irq;
int dma_mrpc_irq;
int rc;

nvecs = pci_alloc_irq_vectors(stdev->pdev, 1, 4,
PCI_IRQ_MSIX | PCI_IRQ_MSI);
Expand All @@ -1196,9 +1242,29 @@ static int switchtec_init_isr(struct switchtec_dev *stdev)
if (event_irq < 0)
return event_irq;

return devm_request_irq(&stdev->pdev->dev, event_irq,
rc = devm_request_irq(&stdev->pdev->dev, event_irq,
switchtec_event_isr, 0,
KBUILD_MODNAME, stdev);

if (rc)
return rc;

if (!stdev->dma_mrpc)
return rc;

dma_mrpc_irq = ioread32(&stdev->mmio_mrpc->dma_vector);
if ( dma_mrpc_irq < 0 || dma_mrpc_irq >= nvecs)
return -EFAULT;

dma_mrpc_irq = pci_irq_vector(stdev->pdev, dma_mrpc_irq);
if (event_irq < 0)
return dma_mrpc_irq;

rc = devm_request_irq(&stdev->pdev->dev, dma_mrpc_irq,
switchtec_dma_mrpc_isr, 0,
KBUILD_MODNAME, stdev);

return rc;
}

static void init_pff(struct switchtec_dev *stdev)
Expand Down Expand Up @@ -1264,6 +1330,17 @@ static int switchtec_init_pci(struct switchtec_dev *stdev,

pci_set_drvdata(pdev, stdev);

if (!use_dma_mrpc)
return 0;

if(!(ioread32(&stdev->mmio_mrpc->dma_ver)? true : false))
return 0;

stdev->dma_mrpc = dma_zalloc_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc),
&stdev->dma_mrpc_dma_addr, GFP_KERNEL);
if (stdev->dma_mrpc == NULL)
return -ENOMEM;

return 0;
}

Expand Down Expand Up @@ -1295,6 +1372,9 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
&stdev->mmio_part_cfg->mrpc_comp_hdr);
enable_link_state_events(stdev);

if (stdev->dma_mrpc)
enable_dma_mrpc(stdev);

rc = cdev_device_add(&stdev->cdev, &stdev->dev);
if (rc)
goto err_devadd;
Expand All @@ -1320,7 +1400,6 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
cdev_device_del(&stdev->cdev, &stdev->dev);
ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
dev_info(&stdev->dev, "unregistered.\n");

stdev_kill(stdev);
put_device(&stdev->dev);
}
Expand Down