Files
linux-nv-oot/drivers/net/ethernet/mft/nnt_driver/nnt_ioctl.c
Bharath H S bf89e2d98e mft: Initial copy of mft source
Add initial mft source of version-4.26.1-3 from
https://www.mellanox.com/downloads/MFT/mft-4.26.1-3-arm64-deb.tgz

bug 4192483
bug 4312056

Change-Id: I77c0af297c9833c3dcbcdfc89b316042548b9af8
Signed-off-by: Bharath H S <bhs@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3069977
(cherry picked from commit d65df2a986469950aab3f323bbee3a3aee0c0308)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3069972
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
2024-04-02 23:01:51 -07:00

231 lines
7.4 KiB
C

#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/uaccess.h>
#include <linux/highmem.h>
#include <linux/sched.h>
#include "nnt_dma.h"
#include "nnt_defs.h"
#include "nnt_pci_conf_access.h"
unsigned int mask = 0x7fff;
unsigned int msb_mask = 0x8000;
int dma_pages_ioctl(unsigned int command, void* user_buffer,
struct nnt_device* nnt_device)
{
struct nnt_page_info page_info;
int error_code = 0;
/* Copy the page info structure from user space. */
if (copy_from_user(&page_info, user_buffer,
sizeof(struct nnt_page_info))) {
error_code = -EFAULT;
goto ReturnOnFinished;
}
if (command == NNT_GET_DMA_PAGES) {
if (map_dma_pages(&page_info, nnt_device)) {
goto ReturnOnFinished;
}
/* Return the physical address to the user */
if (copy_to_user(user_buffer, &page_info,
sizeof(struct nnt_page_info)) != 0) {
error_code = -EFAULT;
goto ReturnOnFinished;
}
} else {
error_code =
release_dma_pages(&page_info, nnt_device);
}
ReturnOnFinished:
return error_code;
}
int read_dword_ioctl(void* user_buffer, struct nnt_device* nnt_device)
{
struct nnt_read_dword_from_config_space read_from_cspace;
int error_code = 0;
/* Copy the request from user space. */
if (copy_from_user(&read_from_cspace, user_buffer,
sizeof(struct nnt_read_dword_from_config_space)) != 0) {
error_code = -EFAULT;
goto ReturnOnFinished;
}
/* Read the dword. */
if (read_dword(&read_from_cspace, nnt_device)) {
goto ReturnOnFinished;
}
/* Copy the data to the user space. */
if (copy_to_user(user_buffer, &read_from_cspace,
sizeof(struct nnt_read_dword_from_config_space)) != 0) {
error_code = -EFAULT;
goto ReturnOnFinished;
}
ReturnOnFinished:
return error_code;
}
int get_nnt_device_parameters(struct nnt_device_parameters* nnt_parameters, struct nnt_device* nnt_device)
{
int error = 0;
nnt_parameters->domain = pci_domain_nr(nnt_device->pci_device->bus);
nnt_parameters->bus = nnt_device->pci_device->bus->number;
nnt_parameters->slot = PCI_SLOT(nnt_device->pci_device->devfn);
nnt_parameters->function = PCI_FUNC(nnt_device->pci_device->devfn);
nnt_parameters->pci_memory_bar_address= nnt_device->memory_device.pci_memory_bar_address;
nnt_parameters->device = nnt_device->pci_device->device;
nnt_parameters->vendor = nnt_device->pci_device->vendor;
nnt_parameters->subsystem_device = nnt_device->pci_device->subsystem_device;
nnt_parameters->multifunction = nnt_device->pci_device->multifunction;
nnt_parameters->subsystem_vendor = nnt_device->pci_device->subsystem_vendor;
check_address_space_support(nnt_device);
if (nnt_device->pciconf_device.vendor_specific_capability &&
(nnt_device->pciconf_device.address_space.icmd || nnt_device->pciconf_device.address_space.cr_space ||
nnt_device->pciconf_device.address_space.semaphore)) {
nnt_parameters->vendor_specific_capability = nnt_device->pciconf_device.vendor_specific_capability;
nnt_parameters->vsec_capability_mask = nnt_device->pciconf_device.vsec_capability_mask;
} else {
nnt_parameters->vendor_specific_capability = 0;
}
return error;
}
int pci_connectx_wa(struct nnt_connectx_wa* connectx_wa, struct nnt_device* nnt_device)
{
unsigned int slot_mask;
int error = 0;
/* Is this slot exists ? */
if (nnt_device->memory_device.connectx_wa_slot_p1) {
printk(KERN_DEBUG "Slot exits for file %s, slot:0x%x\n",
nnt_device->device_name, nnt_device->memory_device.connectx_wa_slot_p1);
error = 0;
goto ReturnOnFinished;
}
/* Find first un(set) bit. and remember the slot */
nnt_device->memory_device.connectx_wa_slot_p1= ffs(~nnt_device->memory_device.connectx_wa_slot_p1);
if (nnt_device->memory_device.connectx_wa_slot_p1 == 0 ||
nnt_device->memory_device.connectx_wa_slot_p1 > NNT_CONNECTX_WA_SIZE) {
error = -ENOLCK;
goto ReturnOnFinished;
}
slot_mask = 1 << (nnt_device->memory_device.connectx_wa_slot_p1 - 1);
/* set the slot as taken */
nnt_device->memory_device.connectx_wa_slot_p1 |= slot_mask;
connectx_wa->connectx_wa_slot_p1 = nnt_device->memory_device.connectx_wa_slot_p1;
ReturnOnFinished:
return error;
}
int vpd_read(struct nnt_vpd* vpd, struct nnt_device* nnt_device)
{
unsigned long jiffies_time;
unsigned int address;
unsigned short data;
int is_bit_set = 0;
int error;
/* Sets F bit to zero and write VPD address. */
address = mask & vpd->offset;
error = pci_write_config_word(nnt_device->pci_device, nnt_device->vpd_capability_address + PCI_VPD_ADDR,
address);
CHECK_PCI_WRITE_ERROR(error, nnt_device->vpd_capability_address + PCI_VPD_ADDR,
address);
/* Wait for data until F bit is set with one */
jiffies_time = msecs_to_jiffies(vpd->timeout) + jiffies;
while (time_before(jiffies, jiffies_time)) {
error = pci_read_config_word(nnt_device->pci_device, nnt_device->vpd_capability_address + PCI_VPD_ADDR,
&data);
CHECK_PCI_READ_ERROR(error, nnt_device->vpd_capability_address + PCI_VPD_ADDR);
if (data & msb_mask) {
is_bit_set = 1;
break;
}
cond_resched();
}
if (!is_bit_set) {
printk(KERN_ERR "Failed to retrieve valid data\n");
return -ETIMEDOUT;
}
/* read data */
error = pci_read_config_dword(nnt_device->pci_device, nnt_device->vpd_capability_address + PCI_VPD_DATA,
&vpd->data);
CHECK_PCI_READ_ERROR(error, nnt_device->vpd_capability_address + PCI_VPD_DATA);
ReturnOnFinished:
return error;
}
int vpd_write(struct nnt_vpd* vpd, struct nnt_device* nnt_device)
{
unsigned long jiffies_time;
unsigned int address;
unsigned short data;
int is_bit_set = 0;
int error;
/* Write the user data */
error = pci_write_config_dword(nnt_device->pci_device, nnt_device->vpd_capability_address + PCI_VPD_DATA,
vpd->data);
CHECK_PCI_WRITE_ERROR(error, nnt_device->vpd_capability_address + PCI_VPD_DATA,
vpd->data);
/* sets F bit to one and write VPD addr */
address = msb_mask | (mask & vpd->offset);
error = pci_write_config_word(nnt_device->pci_device, nnt_device->vpd_capability_address + PCI_VPD_ADDR,
address);
CHECK_PCI_WRITE_ERROR(error, nnt_device->vpd_capability_address + PCI_VPD_ADDR,
address);
/* wait for data until F bit is set with zero */
jiffies_time = msecs_to_jiffies(vpd->timeout) + jiffies;
while (time_before(jiffies, jiffies_time)) {
error = pci_read_config_word(nnt_device->pci_device, nnt_device->vpd_capability_address + PCI_VPD_ADDR,
&data);
CHECK_PCI_READ_ERROR(error, nnt_device->vpd_capability_address + PCI_VPD_ADDR);
if (!(data & msb_mask)) {
is_bit_set = 1;
break;
}
cond_resched();
}
if (!is_bit_set) {
printk(KERN_ERR "Failed to retrieve valid data\n");
return -ETIMEDOUT;
}
ReturnOnFinished:
return error;
}