mirror of
https://github.com/corundum/corundum.git
synced 2025-01-16 08:12:53 +08:00
modules/mqnic/: Add platform driver support
Signed-off-by: Joachim Foerster <joachim.foerster@missinglinkelectronics.com>
This commit is contained in:
parent
80d5bda23f
commit
26c70bbb8a
48
modules/mqnic/device-tree-binding.txt
Normal file
48
modules/mqnic/device-tree-binding.txt
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
* Corundum mqnic Ethernet controller
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: Should be "corundum,mqnic"
|
||||||
|
- reg: Address and length of the "control" register set. Optionally a second and
|
||||||
|
third range, the "app" and "ram" register sets may be added.
|
||||||
|
- interrupts: Should contain mqnic interrupt(s)
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- nvmem-cells: Phandle of nvmem cell containing the base MAC address
|
||||||
|
- nvmem-cell-names: Should be "mac-address"
|
||||||
|
- mac-address-increment-byte:
|
||||||
|
Index of base MAC address byte to increment (default: 0x5)
|
||||||
|
- mac-address-increment:
|
||||||
|
Number to add to the chosen base MAC address byte (default: 0x0)
|
||||||
|
- mac-address-local:
|
||||||
|
Boolean, mark derived MAC addresses as "locally administrated"
|
||||||
|
(default: false)
|
||||||
|
- module-eeproms: Array of phandles to SFP module EEPROM node(s)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
mqnic0: ethernet@a0000000 {
|
||||||
|
compatible = "corundum,mqnic";
|
||||||
|
reg = <0x0 0xa0000000 0x0 0x1000000>,
|
||||||
|
<0x0 0xb0000000 0x0 0x1000000>;
|
||||||
|
reg-names = "csr", "app";
|
||||||
|
interrupt-parent = <&gic>;
|
||||||
|
interrupts = <0x0 0x59 0x1>, <0x0 0x5a 0x1>, <0x0 0x5b 0x1>,
|
||||||
|
<0x0 0x5c 0x1>;
|
||||||
|
|
||||||
|
nvmem-cells = <&macaddress>;
|
||||||
|
nvmem-cell-names = "mac-address";
|
||||||
|
|
||||||
|
mac-address-increment = <0x1>;
|
||||||
|
mac-address-local;
|
||||||
|
|
||||||
|
module-eeproms = <&module_eeprom_sfp0>, <&module_eeprom_sfp1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&eeprom {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
macaddress: macaddress@20 {
|
||||||
|
reg = <0x20 0x06>;
|
||||||
|
};
|
||||||
|
};
|
@ -37,7 +37,10 @@
|
|||||||
#define MQNIC_H
|
#define MQNIC_H
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
#endif
|
||||||
|
#include <linux/platform_device.h>
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
@ -93,12 +96,16 @@ struct mqnic_i2c_bus {
|
|||||||
struct mqnic_irq {
|
struct mqnic_irq {
|
||||||
int index;
|
int index;
|
||||||
int irqn;
|
int irqn;
|
||||||
|
char name[16 + 3];
|
||||||
struct atomic_notifier_head nh;
|
struct atomic_notifier_head nh;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mqnic_dev {
|
struct mqnic_dev {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
|
#endif
|
||||||
|
struct platform_device *pfdev;
|
||||||
|
|
||||||
resource_size_t hw_regs_size;
|
resource_size_t hw_regs_size;
|
||||||
phys_addr_t hw_regs_phys;
|
phys_addr_t hw_regs_phys;
|
||||||
@ -446,6 +453,7 @@ void free_reg_block_list(struct reg_block *list);
|
|||||||
// mqnic_irq.c
|
// mqnic_irq.c
|
||||||
int mqnic_irq_init_pcie(struct mqnic_dev *mdev);
|
int mqnic_irq_init_pcie(struct mqnic_dev *mdev);
|
||||||
void mqnic_irq_deinit_pcie(struct mqnic_dev *mdev);
|
void mqnic_irq_deinit_pcie(struct mqnic_dev *mdev);
|
||||||
|
int mqnic_irq_init_platform(struct mqnic_dev *mdev);
|
||||||
|
|
||||||
// mqnic_dev.c
|
// mqnic_dev.c
|
||||||
extern const struct file_operations mqnic_fops;
|
extern const struct file_operations mqnic_fops;
|
||||||
|
@ -38,6 +38,14 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
/* platform driver OF-related definitions */
|
||||||
|
#define MQNIC_PROP_MAC_ADDR_INC_BYTE "mac-address-increment-byte"
|
||||||
|
#define MQNIC_PROP_MAC_ADDR_INC "mac-address-increment"
|
||||||
|
#define MQNIC_PROP_MAC_ADDR_LOCAL "mac-address-local"
|
||||||
|
#define MQNIC_PROP_MODULE_EEPROM "module-eeproms"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MQNIC_MAX_IRQ 32
|
#define MQNIC_MAX_IRQ 32
|
||||||
|
|
||||||
#define MQNIC_MAX_IF 8
|
#define MQNIC_MAX_IF 8
|
||||||
|
@ -107,3 +107,45 @@ void mqnic_irq_deinit_pcie(struct mqnic_dev *mdev)
|
|||||||
|
|
||||||
pci_free_irq_vectors(pdev);
|
pci_free_irq_vectors(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mqnic_irq_init_platform(struct mqnic_dev *mdev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = mdev->pfdev;
|
||||||
|
struct device *dev = mdev->dev;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
// Allocate IRQs
|
||||||
|
mdev->irq_count = platform_irq_count(pdev);
|
||||||
|
|
||||||
|
// Set up interrupts
|
||||||
|
for (k = 0; k < mdev->irq_count; k++) {
|
||||||
|
int irqn;
|
||||||
|
struct mqnic_irq *irq;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
irqn = platform_get_irq(pdev, k);
|
||||||
|
if (irqn < 0)
|
||||||
|
return irqn;
|
||||||
|
|
||||||
|
irq = devm_kzalloc(dev, sizeof(*irq), GFP_KERNEL);
|
||||||
|
if (!irq)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ATOMIC_INIT_NOTIFIER_HEAD(&irq->nh);
|
||||||
|
|
||||||
|
snprintf(irq->name, sizeof(irq->name), "%s-%u", mdev->name, k);
|
||||||
|
ret = devm_request_irq(dev, irqn, mqnic_irq_handler, 0, irq->name, irq);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "Failed to request IRQ %d (interrupt number %d)", k, irqn);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq->index = k;
|
||||||
|
irq->irqn = irqn;
|
||||||
|
mdev->irq[k] = irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(dev, "Configured %d IRQs", mdev->irq_count);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -59,6 +59,7 @@ MODULE_PARM_DESC(num_tx_queue_entries, "number of entries to allocate per transm
|
|||||||
module_param_named(num_rx_queue_entries, mqnic_num_rx_queue_entries, uint, 0444);
|
module_param_named(num_rx_queue_entries, mqnic_num_rx_queue_entries, uint, 0444);
|
||||||
MODULE_PARM_DESC(num_rx_queue_entries, "number of entries to allocate per receive queue (default: 1024)");
|
MODULE_PARM_DESC(num_rx_queue_entries, "number of entries to allocate per receive queue (default: 1024)");
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
static const struct pci_device_id mqnic_pci_id_table[] = {
|
static const struct pci_device_id mqnic_pci_id_table[] = {
|
||||||
{PCI_DEVICE(0x1234, 0x1001)},
|
{PCI_DEVICE(0x1234, 0x1001)},
|
||||||
{PCI_DEVICE(0x5543, 0x1001)},
|
{PCI_DEVICE(0x5543, 0x1001)},
|
||||||
@ -66,6 +67,15 @@ static const struct pci_device_id mqnic_pci_id_table[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(pci, mqnic_pci_id_table);
|
MODULE_DEVICE_TABLE(pci, mqnic_pci_id_table);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static struct of_device_id mqnic_of_id_table[] = {
|
||||||
|
{ .compatible = "corundum,mqnic" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, mqnic_of_id_table);
|
||||||
|
#endif
|
||||||
|
|
||||||
static LIST_HEAD(mqnic_devices);
|
static LIST_HEAD(mqnic_devices);
|
||||||
static DEFINE_SPINLOCK(mqnic_devices_lock);
|
static DEFINE_SPINLOCK(mqnic_devices_lock);
|
||||||
@ -107,6 +117,133 @@ static void mqnic_free_id(struct mqnic_dev *mqnic)
|
|||||||
spin_unlock(&mqnic_devices_lock);
|
spin_unlock(&mqnic_devices_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mqnic_common_setdma(struct mqnic_dev *mqnic)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct device *dev = mqnic->dev;
|
||||||
|
|
||||||
|
// Set mask
|
||||||
|
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
|
||||||
|
if (ret) {
|
||||||
|
dev_warn(dev, "Warning: failed to set 64 bit PCI DMA mask");
|
||||||
|
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to set PCI DMA mask");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set max segment size
|
||||||
|
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static int mqnic_platform_get_mac_address(struct mqnic_dev *mqnic)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct device *dev = mqnic->dev;
|
||||||
|
char mac_base[ETH_ALEN];
|
||||||
|
struct device_node *np;
|
||||||
|
u32 inc_idx;
|
||||||
|
u32 inc;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
/* NOTE: Not being able to get a (base) MAC address shall not be an
|
||||||
|
* error to fail on intentionally. Thus we are warning, only.
|
||||||
|
*/
|
||||||
|
ret = eth_platform_get_mac_address(dev, mac_base);
|
||||||
|
if (ret) {
|
||||||
|
dev_warn(dev, "Unable to get MAC address\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
np = mqnic->dev->of_node;
|
||||||
|
if (!np)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (of_property_read_u32(np, MQNIC_PROP_MAC_ADDR_INC_BYTE, &inc_idx))
|
||||||
|
inc_idx = 5;
|
||||||
|
if ((inc_idx < 3) || (inc_idx > 5)) {
|
||||||
|
dev_err(dev, "Invalid property \"" MQNIC_PROP_MAC_ADDR_INC_BYTE "\"\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = of_property_read_u32(np, MQNIC_PROP_MAC_ADDR_INC, &inc);
|
||||||
|
if (ret == -EINVAL) {
|
||||||
|
inc = 0;
|
||||||
|
} else if (ret) {
|
||||||
|
dev_err(dev, "Invalid property \"" MQNIC_PROP_MAC_ADDR_INC "\"\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (of_property_read_bool(np, MQNIC_PROP_MAC_ADDR_LOCAL))
|
||||||
|
mac_base[0] |= BIT(1);
|
||||||
|
|
||||||
|
mqnic->mac_count = mqnic->if_count;
|
||||||
|
for (k = 0; k < mqnic->mac_count; k++) {
|
||||||
|
memcpy(mqnic->mac_list[k], mac_base, ETH_ALEN);
|
||||||
|
mqnic->mac_list[k][inc_idx] += inc + k;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqnic_platform_module_eeprom_put(struct mqnic_dev *mqnic)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
for (k = 0; k < mqnic->if_count; k++)
|
||||||
|
if (mqnic->mod_i2c_client)
|
||||||
|
put_device(&mqnic->mod_i2c_client[k]->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mqnic_platform_module_eeprom_get(struct mqnic_dev *mqnic)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct device *dev = mqnic->dev;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
if (!dev->of_node)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (k = 0; k < mqnic->if_count; k++) {
|
||||||
|
struct device_node *np;
|
||||||
|
struct i2c_client *cl;
|
||||||
|
|
||||||
|
/* NOTE: Not being able to get a phandle for module EEPROM shall
|
||||||
|
* not be an error to fail on intentionally. Thus we are
|
||||||
|
* warning, only.
|
||||||
|
*/
|
||||||
|
np = of_parse_phandle(dev->of_node, MQNIC_PROP_MODULE_EEPROM, k);
|
||||||
|
if (!np) {
|
||||||
|
dev_warn(dev, "Missing phandle to module EEPROM for interface %d\n", k);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl = of_find_i2c_device_by_node(np);
|
||||||
|
if (!cl) {
|
||||||
|
ret = -ENOENT;
|
||||||
|
dev_err(dev, "Failed to find I2C device for module of interface %d\n", k);
|
||||||
|
of_node_put(np);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
mqnic->mod_i2c_client[k] = cl;
|
||||||
|
mqnic->mod_i2c_client_count++;
|
||||||
|
}
|
||||||
|
of_node_put(np);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
mqnic_platform_module_eeprom_put(mqnic);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int mqnic_common_probe(struct mqnic_dev *mqnic)
|
static int mqnic_common_probe(struct mqnic_dev *mqnic)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -198,11 +335,23 @@ static int mqnic_common_probe(struct mqnic_dev *mqnic)
|
|||||||
goto fail_bar_size;
|
goto fail_bar_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Board-specific init
|
if (mqnic->pfdev) {
|
||||||
ret = mqnic_board_init(mqnic);
|
#ifdef CONFIG_OF
|
||||||
if (ret) {
|
ret = mqnic_platform_get_mac_address(mqnic);
|
||||||
dev_err(dev, "Failed to initialize board");
|
if (ret)
|
||||||
goto fail_board;
|
goto fail_board;
|
||||||
|
|
||||||
|
ret = mqnic_platform_module_eeprom_get(mqnic);
|
||||||
|
if (ret)
|
||||||
|
goto fail_board;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
// Board-specific init
|
||||||
|
ret = mqnic_board_init(mqnic);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to initialize board");
|
||||||
|
goto fail_board;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// register PHC
|
// register PHC
|
||||||
@ -281,10 +430,17 @@ static void mqnic_common_remove(struct mqnic_dev *mqnic)
|
|||||||
mqnic_destroy_interface(&mqnic->interface[k]);
|
mqnic_destroy_interface(&mqnic->interface[k]);
|
||||||
|
|
||||||
mqnic_unregister_phc(mqnic);
|
mqnic_unregister_phc(mqnic);
|
||||||
mqnic_board_deinit(mqnic);
|
if (mqnic->pfdev) {
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
mqnic_platform_module_eeprom_put(mqnic);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
mqnic_board_deinit(mqnic);
|
||||||
|
}
|
||||||
free_reg_block_list(mqnic->rb_list);
|
free_reg_block_list(mqnic->rb_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -376,19 +532,10 @@ static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent
|
|||||||
goto fail_enable_device;
|
goto fail_enable_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set mask
|
// Set DMA properties
|
||||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
|
ret = mqnic_common_setdma(mqnic);
|
||||||
if (ret) {
|
if (ret)
|
||||||
dev_warn(dev, "Warning: failed to set 64 bit PCI DMA mask");
|
goto fail_regions;
|
||||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "Failed to set PCI DMA mask");
|
|
||||||
goto fail_regions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set max segment size
|
|
||||||
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
|
|
||||||
|
|
||||||
// Reserve regions
|
// Reserve regions
|
||||||
ret = pci_request_regions(pdev, DRIVER_NAME);
|
ret = pci_request_regions(pdev, DRIVER_NAME);
|
||||||
@ -514,15 +661,156 @@ static struct pci_driver mqnic_pci_driver = {
|
|||||||
.remove = mqnic_pci_remove,
|
.remove = mqnic_pci_remove,
|
||||||
.shutdown = mqnic_pci_shutdown
|
.shutdown = mqnic_pci_shutdown
|
||||||
};
|
};
|
||||||
|
#endif /* CONFIG_PCI */
|
||||||
|
|
||||||
|
static int mqnic_platform_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct mqnic_dev *mqnic;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct resource *res;
|
||||||
|
|
||||||
|
dev_info(dev, DRIVER_NAME " platform probe");
|
||||||
|
|
||||||
|
#ifdef CONFIG_NUMA
|
||||||
|
dev_info(dev, " NUMA node: %d", pdev->dev.numa_node);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mqnic = devm_kzalloc(dev, sizeof(*mqnic), GFP_KERNEL);
|
||||||
|
if (!mqnic)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mqnic->dev = dev;
|
||||||
|
mqnic->pfdev = pdev;
|
||||||
|
platform_set_drvdata(pdev, mqnic);
|
||||||
|
|
||||||
|
// assign ID and add to list
|
||||||
|
mqnic_assign_id(mqnic);
|
||||||
|
|
||||||
|
// Set DMA properties
|
||||||
|
ret = mqnic_common_setdma(mqnic);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
// Reserve and map regions
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
mqnic->hw_regs_size = resource_size(res);
|
||||||
|
mqnic->hw_regs_phys = res->start;
|
||||||
|
|
||||||
|
dev_info(dev, "Control BAR size: %llu", mqnic->hw_regs_size);
|
||||||
|
mqnic->hw_addr = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(mqnic->hw_addr)) {
|
||||||
|
ret = PTR_ERR(mqnic->hw_addr);
|
||||||
|
dev_err(dev, "Failed to map control BAR");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||||
|
if (res) {
|
||||||
|
void __iomem *hw_addr;
|
||||||
|
|
||||||
|
mqnic->app_hw_regs_size = resource_size(res);
|
||||||
|
mqnic->app_hw_regs_phys = res->start;
|
||||||
|
|
||||||
|
dev_info(dev, "Application BAR size: %llu", mqnic->app_hw_regs_size);
|
||||||
|
hw_addr = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(hw_addr)) {
|
||||||
|
ret = PTR_ERR(hw_addr);
|
||||||
|
dev_err(dev, "Failed to map application BAR");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
mqnic->app_hw_addr = hw_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
|
||||||
|
if (res) {
|
||||||
|
void __iomem *hw_addr;
|
||||||
|
|
||||||
|
mqnic->ram_hw_regs_size = resource_size(res);
|
||||||
|
mqnic->ram_hw_regs_phys = res->start;
|
||||||
|
|
||||||
|
dev_info(dev, "RAM BAR size: %llu", mqnic->ram_hw_regs_size);
|
||||||
|
hw_addr = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(hw_addr)) {
|
||||||
|
ret = PTR_ERR(hw_addr);
|
||||||
|
dev_err(dev, "Failed to map RAM BAR");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
mqnic->ram_hw_addr = hw_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up interrupts
|
||||||
|
ret = mqnic_irq_init_platform(mqnic);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to set up interrupts");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common init
|
||||||
|
ret = mqnic_common_probe(mqnic);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
// probe complete
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// error handling
|
||||||
|
fail:
|
||||||
|
mqnic_free_id(mqnic);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mqnic_platform_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct mqnic_dev *mqnic = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
dev_info(&pdev->dev, DRIVER_NAME " platform remove");
|
||||||
|
|
||||||
|
mqnic_common_remove(mqnic);
|
||||||
|
|
||||||
|
mqnic_free_id(mqnic);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver mqnic_platform_driver = {
|
||||||
|
.probe = mqnic_platform_probe,
|
||||||
|
.remove = mqnic_platform_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = DRIVER_NAME,
|
||||||
|
.of_match_table = of_match_ptr(mqnic_of_id_table),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static int __init mqnic_init(void)
|
static int __init mqnic_init(void)
|
||||||
{
|
{
|
||||||
return pci_register_driver(&mqnic_pci_driver);
|
int rc;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
|
rc = pci_register_driver(&mqnic_pci_driver);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = platform_driver_register(&mqnic_platform_driver);
|
||||||
|
if (rc)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
|
pci_unregister_driver(&mqnic_pci_driver);
|
||||||
|
#endif
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit mqnic_exit(void)
|
static void __exit mqnic_exit(void)
|
||||||
{
|
{
|
||||||
|
platform_driver_unregister(&mqnic_platform_driver);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
pci_unregister_driver(&mqnic_pci_driver);
|
pci_unregister_driver(&mqnic_pci_driver);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(mqnic_init);
|
module_init(mqnic_init);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user