Skip to content

Dma mrpc#12

Merged
wesleywesley merged 3 commits intodevelfrom
dma_mrpc
Jun 6, 2018
Merged

Dma mrpc#12
wesleywesley merged 3 commits intodevelfrom
dma_mrpc

Conversation

@wesleywesley
Copy link
Copy Markdown
Contributor

No description provided.

@wesleywesley wesleywesley requested review from a user, kelvin-cao and lsgunth May 30, 2018 09:48
Copy link
Copy Markdown
Collaborator

@lsgunth lsgunth left a comment

Choose a reason for hiding this comment

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

Please also add some better description to the commit message. Especially if you intend on pushing this upstream at some point.

Comment thread linux/switchtec.h Outdated
struct list_head mrpc_queue;
int mrpc_busy;
struct work_struct mrpc_work;
struct work_struct dma_mrpc_work;
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.

Adding registers in a separate patch is a good idea, but adding fields to a structure that you don't use yet is not good practice. Add them when you use them.

Comment thread linux/switchtec.h Outdated

struct switchtec_ntb *sndev;

bool dma_mrpc;
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.

I think this extra bool is unnecessary. Just check if mrpc_output_addr is NULL or not.

Comment thread linux/switchtec.h Outdated

bool dma_mrpc;
struct dma_mrpc_output *mrpc_output_addr;
dma_addr_t mrpc_output_dma;
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.

I don't like the names chosen. mrpc_output_addr is a pointer to a struct, not an address. If we prefix every pointer with _addr then there will be a lot of noise. It also doesn't indicate that this struct is only used for MRPC in DMA mode. Where as mrpc_output_dma is an address...

I'd suggest something like:

struct dma_mrpc_output *dma_mrpc;
dma_addr_t dma_mrpc_dma_addr;

Comment thread switchtec.c Outdated
}
#endif
#endif

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.

Lets not propagate this mess any further than it already is. I've been trying to remove it.

For now, just use readq()/writeq()

Comment thread switchtec.c Outdated
}

static void dma_mrpc_complete_cmd(struct switchtec_dev *stdev)
{
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.

This function is almost identical to mrpc_complete_cmd(). Never cut and paste code. Better to just check if we are doing a DMA transaction and copy it from where appropriate.

Then, I think this should remove the need for the separate work queues, etc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Will combine the two work items and completion functions.

Comment thread switchtec.c Outdated
return rc;

if (stdev->dma_mrpc){
event_irq = ioread32(&stdev->mmio_mrpc->dma_vector);
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.

We should rename event_irq as it now is used for both the event IRQ and the DMA IRQ.

Comment thread switchtec.c Outdated
}


static irqreturn_t switchtec_mrpc_isr(int irq, void *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.

This function name is confusing. It should probably include "dma" somewhere in there. It's assigned to an interrupt the hardware seems to refer to as "dma_vector"... It's not a general MRPC interrupt.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

rename to switchtec_dma_mrpc_isr

Comment thread switchtec.c
@@ -1022,7 +1109,11 @@ static void enable_link_state_events(struct switchtec_dev *stdev)
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.

Comment thread switchtec.c Outdated
err_devadd:
stdev_kill(stdev);
err_put:
stdev_release(&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.

This is wrong and will cause a use after free bug. Notice that stdev_release() will free stdev and the next couple lines then use stdev. In fact stdev_release() is already called only after the last reference to the device is freed. So put_device() may or may not call it depending on if something else still holds a reference to it.

Comment thread switchtec.c Outdated
dev_info(&stdev->dev, "unregistered.\n");

stdev_kill(stdev);
stdev_release(&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.

Also wrong.

Comment thread switchtec.c Outdated
if (stdev->dma_mrpc){
iowrite64(stdev->mrpc_output_dma, &stdev->mmio_mrpc->dma_addr);
iowrite32(SWITCHTEC_DMA_MRPC_EN_IRQ, &stdev->mmio_mrpc->dma_en);
}
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.

Also: very important -- We need to remember to unset dma_addr before we call dma_free_coherent(). We don't want the hardware writing to that memory after it's freed.

It's also not clear to me what enables using DMA transfers. You only seem to set the flag to enable interrupt requests. Does the hardware enable DMA requests once dma_addr is set or is the EN_IRQ flag mis-named?

Also, you might want to consider some of the security implications here. On Windows, any user can now write this DMA address and can use it to scribble on any kernel-space memory. That's really bad. Makes me regret letting your colleagues convince me to allow userspace access to GAS at all... At least on Linux it requires root access and the driver doesn't actually add any privilege userspace didn't already have. Someone should probably look into ensuring GAS access on Windows at least requires elevated privileges, but I'm not sure how that can be done.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Nice capture.
For the dma mrpc new feature: four registers added: enable, address, vector and version.
where version number greater than zero, signify dma mrpc feature is supported; dma mrpc enabled by enable register instead of filling the target address to address register. So, yes, EN_IRQ flag msi-named.
More about the IRQ:
Command register format also change for this new feature.
Where BIT [15:0] keep unchanged, should feed with mrpc command index.
BIT 16, notify or not, where 0 notify, 1 not notify.
Whether the event will trig IRQ or not, is still controlled by BIT 3 of MRPC completion header reg.

Comment thread switchtec.c Outdated
memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data,
stuser->read_len);
if (stdev->dma_mrpc)
memcpy_fromio(stuser->data, &stdev->dma_mrpc->data,
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.

This should be a regular memcpy

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it should be memcpy instead of memcpy_fromio.

Comment thread switchtec.c Outdated
return event_irq;

return devm_request_irq(&stdev->pdev->dev, event_irq,
rc = devm_request_irq(&stdev->pdev->dev, event_irq,
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: There's one too many spaces between = and devm

Comment thread switchtec.c Outdated
return 0;

stdev->dma_mrpc = dma_zalloc_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc),
&stdev->dma_mrpc_dma_addr, GFP_KERNEL);
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: indentation should align with the open parenthesis

Comment thread switchtec.c Outdated
if (stdev->dma_mrpc){
dma_free_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc),
stdev->dma_mrpc, stdev->dma_mrpc_dma_addr);
iowrite32(0, &stdev->mmio_mrpc->dma_en);
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.

I think it's best we also clear the address as well as the enable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

confirm that device side treat dma_mrpc_dma_addr 0 as a invalid address value, none dma operation will executed in 0 value case. So we can deinit the register by 0.
But from PCIe aspect, it is not explicit said in spec, the address 0 is a invalid field in memory write tlp. This is why I hesitate to add clear the address by 0, but just disable dma function

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.

If something goes wrong I'd rather see and have to debug a write to an invalid address of zero than to a valid physical address that the OS isn't expected. The former will at worst produce an error while the latter will be scribbling on random memory in the system which would be a nightmare if it has to be debugged.

@wesleywesley wesleywesley force-pushed the dma_mrpc branch 2 times, most recently from 9c76d92 to 4e6a3b4 Compare June 1, 2018 07:02
1. macro definition for dma mrpc enable bit

2. registers include: enable, dma target address, vector, and version

3. data structure of dma mrpc output
@wesleywesley
Copy link
Copy Markdown
Contributor Author

Hi, Logan, Kelvin, and Joey,

I go through all the comments in this conversations again, it seems that all the suggestion have been adopted.
And also the action items for code review, they are already done.

If no more comments/suggestions, I will merge the pull request into devel branch.

Thank you all for the help and the good/excellent suggestions.

regards,
Wesley

Copy link
Copy Markdown
Collaborator

@lsgunth lsgunth left a comment

Choose a reason for hiding this comment

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

Besides the two kernel style nits I noticed this looks good.

Comment thread switchtec.c
{
struct switchtec_dev *stdev = to_stdev(dev);

if (stdev->dma_mrpc){
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: There should be a blank line after variables are declared.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed, thx.

Comment thread switchtec.c Outdated
&stdev->mmio_part_cfg->mrpc_comp_hdr);
enable_link_state_events(stdev);

if (stdev->dma_mrpc){
Copy link
Copy Markdown
Collaborator

@lsgunth lsgunth Jun 4, 2018

Choose a reason for hiding this comment

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

Style nit: Single line if statements should not have curly brackets.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed, thx.

 1. add dma output target virtual and bus addrss member in switchtec_dev struct

 2. in mrpc completion function, collect the result from different source

 3. release dma output buffer and disable mrpc dma function in stdev_release

 4. add isr for dma mrpc

 5. according to the dma version register value, allocate dma buffer, enable dma function and register interrupt service routine
dma mrpc or legacy mrpc is controllable by this parameter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants