Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • atlas-tdaq-felix/felix-versal-tools/flxnet-drivers
1 result
Show changes
...@@ -30,13 +30,6 @@ ...@@ -30,13 +30,6 @@
#define DRV_NAME "flxnet_dev" #define DRV_NAME "flxnet_dev"
/*
- disable tx and rx on the peers without "link" present
- it's possible to make TX queue circular buffer lockless
- user interrupts instead of timer; use NAPI
*/
struct mutex flxnet_mutex; struct mutex flxnet_mutex;
u32 message_level; u32 message_level;
...@@ -211,19 +204,19 @@ struct flxnet_peer *find_peer_for_netdev(struct net_device *dev) { ...@@ -211,19 +204,19 @@ struct flxnet_peer *find_peer_for_netdev(struct net_device *dev) {
} }
// removes the peer from the network, assumes that peer_mutex is held // removes the peer from the network
void flxnet_remove_peer(struct flxnet_peer *peer) { void flxnet_remove_peer(struct flxnet_peer *peer) {
int rv; int rv;
set_carrier(peer, false);
netif_stop_queue(peer->flxnet);
netif_carrier_off(peer->flxnet);
unregister_netdev(peer->flxnet);
free_netdev(peer->flxnet);
kfree(peer->tx_queue.packets);
if (message_level & NETIF_MSG_LINK) if (message_level & NETIF_MSG_LINK)
pr_info("flxnet_dev: removing peer %p from the network\n", peer); pr_info("flxnet_dev: removing peer %p from the network\n", peer);
mutex_lock(&peer_mutex);
set_carrier(peer, false);
unregister_netdev(peer->flxnet);
free_netdev(peer->flxnet);
kfree(peer->tx_queue.packets);
rv = atomic_dec_return(&peer_count); rv = atomic_dec_return(&peer_count);
if (rv < 0) { if (rv < 0) {
pr_err("flxnet_dev: BUG in %s: peer_count = %d, less than 0\n", pr_err("flxnet_dev: BUG in %s: peer_count = %d, less than 0\n",
...@@ -233,50 +226,9 @@ void flxnet_remove_peer(struct flxnet_peer *peer) { ...@@ -233,50 +226,9 @@ void flxnet_remove_peer(struct flxnet_peer *peer) {
list_del(&peer->list_head); list_del(&peer->list_head);
kfree(peer); kfree(peer);
mutex_unlock(&peer_mutex);
} }
// mark as not reserved so that peer modules can be removed
//void flxnet_release_all_peers(void) {
// struct flxnet_peer *peer;
// struct flxnet_peer *tmp;
//
// mutex_lock(&peer_mutex);
// list_for_each_entry_safe(peer, tmp, &peers, list_head) {
// if (peer->reserved) {
// module_put(peer->owner);
// peer->reserved = false;
// } else {
// if (message_level & NETIF_MSG_DRV)
// pr_info("flxnet_dev: trying to release peer %p, which is not reserved, skipping\n", peer);
// }
// }
// mutex_unlock(&peer_mutex);
//}
// mark as reserved so that peer modules cannot be removed and iomem stay there
//void flxnet_reserve_all_peers(void) {
// struct flxnet_peer *peer;
// struct flxnet_peer *tmp;
//
// mutex_lock(&peer_mutex);
// list_for_each_entry_safe(peer, tmp, &peers, list_head) {
// if (!peer->reserved) {
// peer->reserved = try_module_get(peer->owner);
// if (!peer->reserved) {
// pr_err("flxnet_dev: failed to reserve peer %p, owner module is missing\n", peer);
// flxnet_remove_peer(peer);
// }
// } else {
// if (message_level & NETIF_MSG_DRV)
// pr_info("flxnet_dev: trying to reserve peer %p, which is already reserved, skipping\n", peer);
// }
// }
// mutex_unlock(&peer_mutex);
//}
static bool tx_queue_is_full(struct flxnet_peer *peer) { static bool tx_queue_is_full(struct flxnet_peer *peer) {
bool rv; bool rv;
unsigned long flags; unsigned long flags;
...@@ -579,7 +531,6 @@ static inline void check_carrier(struct flxnet_peer *peer) { ...@@ -579,7 +531,6 @@ static inline void check_carrier(struct flxnet_peer *peer) {
if (!netif_carrier_ok(peer->flxnet)) { if (!netif_carrier_ok(peer->flxnet)) {
if (message_level & NETIF_MSG_IFUP) if (message_level & NETIF_MSG_IFUP)
pr_info("flxnet_dev: status carrier changed to %d\n", carrier); pr_info("flxnet_dev: status carrier changed to %d\n", carrier);
netif_start_queue(peer->flxnet);
netif_carrier_on(peer->flxnet); netif_carrier_on(peer->flxnet);
} }
} }
...@@ -587,7 +538,6 @@ static inline void check_carrier(struct flxnet_peer *peer) { ...@@ -587,7 +538,6 @@ static inline void check_carrier(struct flxnet_peer *peer) {
if (netif_carrier_ok(peer->flxnet)) { if (netif_carrier_ok(peer->flxnet)) {
if (message_level & NETIF_MSG_IFDOWN) if (message_level & NETIF_MSG_IFDOWN)
pr_info("flxnet_dev: status carrier changed to %d\n", carrier); pr_info("flxnet_dev: status carrier changed to %d\n", carrier);
netif_stop_queue(peer->flxnet);
netif_carrier_off(peer->flxnet); netif_carrier_off(peer->flxnet);
} }
} }
...@@ -605,7 +555,6 @@ void recv_timer_function(struct timer_list *timer_list) { ...@@ -605,7 +555,6 @@ void recv_timer_function(struct timer_list *timer_list) {
bool can_transmit_packets(struct flxnet_peer *peer) { bool can_transmit_packets(struct flxnet_peer *peer) {
if (is_magic_correct(peer) && can_accept_block(peer)) { if (is_magic_correct(peer) && can_accept_block(peer)) {
mutex_unlock(&peer_mutex);
return true; return true;
} }
return false; return false;
...@@ -712,8 +661,6 @@ int send_recv_thread(void *data) { ...@@ -712,8 +661,6 @@ int send_recv_thread(void *data) {
int open(struct net_device *dev) { int open(struct net_device *dev) {
mutex_lock(&flxnet_mutex); mutex_lock(&flxnet_mutex);
//flxnet_reserve_all_peers(); // reserve the modules that supplied the peers
tx_queue_reset(dev); // clear TX queue tx_queue_reset(dev); // clear TX queue
// enable RX side // enable RX side
...@@ -733,7 +680,6 @@ int open(struct net_device *dev) { ...@@ -733,7 +680,6 @@ int open(struct net_device *dev) {
if (message_level & NETIF_MSG_IFUP) if (message_level & NETIF_MSG_IFUP)
pr_info("flxnet_dev: start netif queue\n"); pr_info("flxnet_dev: start netif queue\n");
netif_start_queue(dev); netif_start_queue(dev);
netif_carrier_on(dev);
mutex_unlock(&flxnet_mutex); mutex_unlock(&flxnet_mutex);
return 0; return 0;
...@@ -753,11 +699,8 @@ int stop(struct net_device *dev) { ...@@ -753,11 +699,8 @@ int stop(struct net_device *dev) {
if (message_level & NETIF_MSG_IFDOWN) if (message_level & NETIF_MSG_IFDOWN)
pr_info("flxnet_dev: stop netif queue\n"); pr_info("flxnet_dev: stop netif queue\n");
netif_stop_queue(dev); netif_stop_queue(dev);
netif_carrier_off(dev);
tx_queue_reset(dev); // clear TX queue tx_queue_reset(dev); // clear TX queue
//flxnet_release_all_peers(); // free the modules that supplied the peers
mutex_unlock(&flxnet_mutex); mutex_unlock(&flxnet_mutex);
return 0; return 0;
...@@ -1042,10 +985,12 @@ err_alloc_tx_queue: ...@@ -1042,10 +985,12 @@ err_alloc_tx_queue:
} }
// add a felix device to the network // add a peer device to the network
struct flxnet_peer * flxnet_add_peer(void* __iomem base_address) { struct flxnet_peer * flxnet_add_peer(void* __iomem base_address) {
struct flxnet_peer *peer; struct flxnet_peer *peer;
pr_info("flxnet_dev: flxnet_add_peer %lX\n", (long unsigned int)base_address); pr_info("flxnet_dev: flxnet_add_peer %lX\n", (long unsigned int)base_address);
mutex_lock(&peer_mutex);
peer = kzalloc(sizeof(struct flxnet_peer), GFP_KERNEL); peer = kzalloc(sizeof(struct flxnet_peer), GFP_KERNEL);
if (IS_ERR(peer)) { if (IS_ERR(peer)) {
pr_err("flxnet_dev: can't allocate memory for struct flxnet_peer\n"); pr_err("flxnet_dev: can't allocate memory for struct flxnet_peer\n");
...@@ -1071,7 +1016,7 @@ struct flxnet_peer * flxnet_add_peer(void* __iomem base_address) { ...@@ -1071,7 +1016,7 @@ struct flxnet_peer * flxnet_add_peer(void* __iomem base_address) {
if (message_level & NETIF_MSG_IFUP) if (message_level & NETIF_MSG_IFUP)
pr_info("flxnet_dev: status_carrier %d\n", status_carrier(peer)); pr_info("flxnet_dev: status_carrier %d\n", status_carrier(peer));
list_add(&peers, &peer->list_head); list_add(&peer->list_head, &peers);
atomic_inc(&peer_count); atomic_inc(&peer_count);
mutex_unlock(&peer_mutex); mutex_unlock(&peer_mutex);
...@@ -1091,24 +1036,8 @@ int __init flxnet_dev_init(void) { ...@@ -1091,24 +1036,8 @@ int __init flxnet_dev_init(void) {
return 0; return 0;
} }
// unregister the network device if necessary
void __exit flxnet_dev_exit(void) { void __exit flxnet_dev_exit(void) {
struct flxnet_peer *peer, *tmp;
if (!list_empty(&peers)) {
mutex_lock(&peer_mutex);
list_for_each_entry_safe(peer, tmp, &peers, list_head) {
netif_stop_queue(peer->flxnet);
netif_carrier_off(peer->flxnet);
unregister_netdev(peer->flxnet);
free_netdev(peer->flxnet);
kfree(peer->tx_queue.packets);
}
pr_info("flxnet_dev: unregistred network device\n");
}
pr_info("flxnet_dev: removing %s driver\n", DRV_NAME); pr_info("flxnet_dev: removing %s driver\n", DRV_NAME);
mutex_unlock(&peer_mutex);
mutex_destroy(&peer_mutex); mutex_destroy(&peer_mutex);
mutex_destroy(&flxnet_mutex); mutex_destroy(&flxnet_mutex);
} }
......
...@@ -37,7 +37,6 @@ struct pcie_flx_serial_device { ...@@ -37,7 +37,6 @@ struct pcie_flx_serial_device {
struct pci_dev *pdev; // pci device struct from probe() struct pci_dev *pdev; // pci device struct from probe()
void __iomem *bar; // addresses for the relevant BAR void __iomem *bar; // addresses for the relevant BAR
int bar_idx; int bar_idx;
spinlock_t lock; // protects concurrent access
unsigned int flags; unsigned int flags;
struct flxnet_peer * peer; struct flxnet_peer * peer;
...@@ -66,11 +65,16 @@ static int flxnet_pcie_init(void) { ...@@ -66,11 +65,16 @@ static int flxnet_pcie_init(void) {
// if a PCI device is found, a pointer to its device structure is returned // if a PCI device is found, a pointer to its device structure is returned
pdev = pci_get_device(0x10dc, 0x0427, pdev); pdev = pci_get_device(0x10dc, 0x0427, pdev);
if (pdev == NULL) {
pr_info("flxnet_pcie: no pcie devices available\n");
return 0;
}
// pdev returns NULL when all the PCI devices are found and stops searching // pdev returns NULL when all the PCI devices are found and stops searching
while (pdev != NULL) { while (pdev != NULL) {
pr_info("flxnet_pcie: found %s \n", pci_name(pdev)); pr_info("flxnet_pcie: found %s \n", pci_name(pdev));
rv = configure_pcie_device(pdev); rv = configure_pcie_device(pdev);
pci_dev_put(pdev);
if (rv < 0) { if (rv < 0) {
pr_warn("flxnet_pcie: failed to configure %s\n", pci_name(pdev)); pr_warn("flxnet_pcie: failed to configure %s\n", pci_name(pdev));
} }
...@@ -84,6 +88,7 @@ static int flxnet_pcie_init(void) { ...@@ -84,6 +88,7 @@ static int flxnet_pcie_init(void) {
return rv; return rv;
} }
// deconfigure pcie devices if necessary, remove module // deconfigure pcie devices if necessary, remove module
static void flxnet_pcie_exit(void) { static void flxnet_pcie_exit(void) {
...@@ -95,8 +100,9 @@ static void flxnet_pcie_exit(void) { ...@@ -95,8 +100,9 @@ static void flxnet_pcie_exit(void) {
pr_info("flxnet_pcie: list not empty - deconfiguring PCIe devices\n"); pr_info("flxnet_pcie: list not empty - deconfiguring PCIe devices\n");
list_for_each_entry_safe(fdev, tmp, &flx_devices, list_head) { list_for_each_entry_safe(fdev, tmp, &flx_devices, list_head) {
flxnet_remove_peer(fdev->peer); flxnet_remove_peer(fdev->peer);
list_del(&fdev->list_head);
deconfigure_device(fdev); deconfigure_device(fdev);
} }
} }
else { else {
pr_info("flxnet_pcie: list is empty - nothing to deconfigure\n"); pr_info("flxnet_pcie: list is empty - nothing to deconfigure\n");
...@@ -104,6 +110,7 @@ static void flxnet_pcie_exit(void) { ...@@ -104,6 +110,7 @@ static void flxnet_pcie_exit(void) {
} }
// configure a felix serial device
static int configure_pcie_device(struct pci_dev *pdev) { static int configure_pcie_device(struct pci_dev *pdev) {
int rv; int rv;
...@@ -120,7 +127,6 @@ static int configure_pcie_device(struct pci_dev *pdev) { ...@@ -120,7 +127,6 @@ static int configure_pcie_device(struct pci_dev *pdev) {
if (!fdev) if (!fdev)
return -ENOMEM; return -ENOMEM;
spin_lock_init(&fdev->lock);
fdev->magic = FLX_PCIE_MAGIC; fdev->magic = FLX_PCIE_MAGIC;
fdev->pdev = pdev; fdev->pdev = pdev;
fdev->bar_idx = bar_idx; fdev->bar_idx = bar_idx;
...@@ -132,6 +138,7 @@ static int configure_pcie_device(struct pci_dev *pdev) { ...@@ -132,6 +138,7 @@ static int configure_pcie_device(struct pci_dev *pdev) {
pr_err("flxnet_pcie: pci_enable_device() failed, %d\n", rv); pr_err("flxnet_pcie: pci_enable_device() failed, %d\n", rv);
goto err_enable; goto err_enable;
} }
pci_dev_get(pdev);
// reserve the selected bar for this driver // reserve the selected bar for this driver
pr_info("flxnet_pcie: reserving BAR memory\n"); pr_info("flxnet_pcie: reserving BAR memory\n");
...@@ -146,7 +153,8 @@ static int configure_pcie_device(struct pci_dev *pdev) { ...@@ -146,7 +153,8 @@ static int configure_pcie_device(struct pci_dev *pdev) {
rv = map_single_bar(fdev, bar_idx); rv = map_single_bar(fdev, bar_idx);
if (rv < 0) { if (rv < 0) {
goto warn_nobar; goto warn_nobar;
} else if (rv < MIN_MMAP_SIZE) { }
else if (rv < MIN_MMAP_SIZE) {
pr_err("flxnet_pcie: mapped region is too small (%d bytes < %d)\n", pr_err("flxnet_pcie: mapped region is too small (%d bytes < %d)\n",
rv, MIN_MMAP_SIZE); rv, MIN_MMAP_SIZE);
goto err_peer; goto err_peer;
...@@ -161,6 +169,7 @@ static int configure_pcie_device(struct pci_dev *pdev) { ...@@ -161,6 +169,7 @@ static int configure_pcie_device(struct pci_dev *pdev) {
goto err_peer; goto err_peer;
} }
// device structure // device structure
list_add(&fdev->list_head, &flx_devices); list_add(&fdev->list_head, &flx_devices);
pr_info("flxnet_pcie: added peer to list flx_devices\n"); pr_info("flxnet_pcie: added peer to list flx_devices\n");
...@@ -207,20 +216,17 @@ static void deconfigure_device(struct pcie_flx_serial_device *fdev) { ...@@ -207,20 +216,17 @@ static void deconfigure_device(struct pcie_flx_serial_device *fdev) {
if (!pdev) { if (!pdev) {
pr_err("flxnet_pcie: pci_dev ptr is NULL\n"); pr_err("flxnet_pcie: pci_dev ptr is NULL\n");
goto err_exit;
} }
if (fdev->bar) { if (fdev->bar) {
pci_iounmap(pdev, fdev->bar); pci_iounmap(pdev, fdev->bar);
} else { } else {
pr_err("flxnet_pcie: BAR memory is not mapped\n"); pr_warn("flxnet_pcie: BAR memory is not mapped\n");
} }
pci_dev_put(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
pci_release_region(pdev, bar_idx); pci_release_region(pdev, bar_idx);
err_exit:
list_del(&fdev->list_head);
kfree(fdev); kfree(fdev);
} }
......