aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_main.c
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2009-03-09 04:50:54 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-10 08:10:02 -0400
commit9f5bc7f1908665d7cf379f698c7bdc53bc10da85 (patch)
treed55c0e6646af2c1f4093d3909329752110c3a54b /drivers/net/netxen/netxen_nic_main.c
parentd32cc3d24eace8a271a39ffe8aeae1861f400d2d (diff)
netxen: refactor netdev open close
rearrange open and close into hardware attach(), detach() and nic up() and down(). this will be used for suspend/resume subsequently. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r--drivers/net/netxen/netxen_nic_main.c302
1 files changed, 166 insertions, 136 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index c9519843f8cb..2953a83bc856 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -94,20 +94,6 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
94 94
95MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); 95MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
96 96
97/*
98 * In netxen_nic_down(), we must wait for any pending callback requests into
99 * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be
100 * reenabled right after it is deleted in netxen_nic_down().
101 * FLUSH_SCHEDULED_WORK() does this synchronization.
102 *
103 * Normally, schedule_work()/flush_scheduled_work() could have worked, but
104 * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off()
105 * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a
106 * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause
107 * linkwatch_event() to be executed which also attempts to acquire the rtnl
108 * lock thus causing a deadlock.
109 */
110
111static struct workqueue_struct *netxen_workq; 97static struct workqueue_struct *netxen_workq;
112#define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp) 98#define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp)
113#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq) 99#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq)
@@ -722,6 +708,163 @@ netxen_start_firmware(struct netxen_adapter *adapter)
722 return 0; 708 return 0;
723} 709}
724 710
711static int
712netxen_nic_request_irq(struct netxen_adapter *adapter)
713{
714 irq_handler_t handler;
715 unsigned long flags = IRQF_SAMPLE_RANDOM;
716 struct net_device *netdev = adapter->netdev;
717
718 if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) ||
719 (adapter->intr_scheme != INTR_SCHEME_PERPORT)) {
720 printk(KERN_ERR "%s: Firmware interrupt scheme is "
721 "incompatible with driver\n",
722 netdev->name);
723 adapter->driver_mismatch = 1;
724 return -EINVAL;
725 }
726
727 if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
728 handler = netxen_msix_intr;
729 else if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
730 handler = netxen_msi_intr;
731 else {
732 flags |= IRQF_SHARED;
733 handler = netxen_intr;
734 }
735 adapter->irq = netdev->irq;
736
737 return request_irq(adapter->irq, handler,
738 flags, netdev->name, adapter);
739}
740
741static int
742netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
743{
744 int err;
745
746 err = adapter->init_port(adapter, adapter->physical_port);
747 if (err) {
748 printk(KERN_ERR "%s: Failed to initialize port %d\n",
749 netxen_nic_driver_name, adapter->portnum);
750 return err;
751 }
752 adapter->macaddr_set(adapter, netdev->dev_addr);
753
754 netxen_nic_set_link_parameters(adapter);
755
756 netxen_set_multicast_list(netdev);
757 if (adapter->set_mtu)
758 adapter->set_mtu(adapter, netdev->mtu);
759
760 adapter->ahw.linkup = 0;
761 mod_timer(&adapter->watchdog_timer, jiffies);
762
763 napi_enable(&adapter->napi);
764 netxen_nic_enable_int(adapter);
765
766 return 0;
767}
768
769static void
770netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
771{
772 netif_carrier_off(netdev);
773 netif_stop_queue(netdev);
774 napi_disable(&adapter->napi);
775
776 if (adapter->stop_port)
777 adapter->stop_port(adapter);
778
779 netxen_nic_disable_int(adapter);
780
781 netxen_release_tx_buffers(adapter);
782
783 FLUSH_SCHEDULED_WORK();
784 del_timer_sync(&adapter->watchdog_timer);
785}
786
787
788static int
789netxen_nic_attach(struct netxen_adapter *adapter)
790{
791 struct net_device *netdev = adapter->netdev;
792 struct pci_dev *pdev = adapter->pdev;
793 int err, ctx, ring;
794
795 err = netxen_init_firmware(adapter);
796 if (err != 0) {
797 printk(KERN_ERR "Failed to init firmware\n");
798 return -EIO;
799 }
800
801 if (adapter->fw_major < 4)
802 adapter->max_rds_rings = 3;
803 else
804 adapter->max_rds_rings = 2;
805
806 err = netxen_alloc_sw_resources(adapter);
807 if (err) {
808 printk(KERN_ERR "%s: Error in setting sw resources\n",
809 netdev->name);
810 return err;
811 }
812
813 netxen_nic_clear_stats(adapter);
814
815 err = netxen_alloc_hw_resources(adapter);
816 if (err) {
817 printk(KERN_ERR "%s: Error in setting hw resources\n",
818 netdev->name);
819 goto err_out_free_sw;
820 }
821
822 if (adapter->fw_major < 4) {
823 adapter->crb_addr_cmd_producer =
824 crb_cmd_producer[adapter->portnum];
825 adapter->crb_addr_cmd_consumer =
826 crb_cmd_consumer[adapter->portnum];
827
828 netxen_nic_update_cmd_producer(adapter, 0);
829 netxen_nic_update_cmd_consumer(adapter, 0);
830 }
831
832 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
833 for (ring = 0; ring < adapter->max_rds_rings; ring++)
834 netxen_post_rx_buffers(adapter, ctx, ring);
835 }
836
837 err = netxen_nic_request_irq(adapter);
838 if (err) {
839 dev_err(&pdev->dev, "%s: failed to setup interrupt\n",
840 netdev->name);
841 goto err_out_free_rxbuf;
842 }
843
844 adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
845 return 0;
846
847err_out_free_rxbuf:
848 netxen_release_rx_buffers(adapter);
849 netxen_free_hw_resources(adapter);
850err_out_free_sw:
851 netxen_free_sw_resources(adapter);
852 return err;
853}
854
855static void
856netxen_nic_detach(struct netxen_adapter *adapter)
857{
858 if (adapter->irq)
859 free_irq(adapter->irq, adapter);
860
861 netxen_release_rx_buffers(adapter);
862 netxen_free_hw_resources(adapter);
863 netxen_free_sw_resources(adapter);
864
865 adapter->is_up = 0;
866}
867
725static int __devinit 868static int __devinit
726netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 869netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
727{ 870{
@@ -973,9 +1116,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
973 unregister_netdev(netdev); 1116 unregister_netdev(netdev);
974 1117
975 if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { 1118 if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
976 netxen_free_hw_resources(adapter); 1119 netxen_nic_detach(adapter);
977 netxen_release_rx_buffers(adapter);
978 netxen_free_sw_resources(adapter);
979 1120
980 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) 1121 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
981 netxen_p3_free_mac_list(adapter); 1122 netxen_p3_free_mac_list(adapter);
@@ -984,9 +1125,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
984 if (adapter->portnum == 0) 1125 if (adapter->portnum == 0)
985 netxen_free_adapter_offload(adapter); 1126 netxen_free_adapter_offload(adapter);
986 1127
987 if (adapter->irq)
988 free_irq(adapter->irq, adapter);
989
990 netxen_teardown_intr(adapter); 1128 netxen_teardown_intr(adapter);
991 1129
992 netxen_cleanup_pci_map(adapter); 1130 netxen_cleanup_pci_map(adapter);
@@ -998,125 +1136,30 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
998 free_netdev(netdev); 1136 free_netdev(netdev);
999} 1137}
1000 1138
1001/*
1002 * Called when a network interface is made active
1003 * @returns 0 on success, negative value on failure
1004 */
1005static int netxen_nic_open(struct net_device *netdev) 1139static int netxen_nic_open(struct net_device *netdev)
1006{ 1140{
1007 struct netxen_adapter *adapter = netdev_priv(netdev); 1141 struct netxen_adapter *adapter = netdev_priv(netdev);
1008 int err = 0; 1142 int err = 0;
1009 int ctx, ring;
1010 irq_handler_t handler;
1011 unsigned long flags = IRQF_SAMPLE_RANDOM;
1012 1143
1013 if (adapter->driver_mismatch) 1144 if (adapter->driver_mismatch)
1014 return -EIO; 1145 return -EIO;
1015 1146
1016 if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { 1147 if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
1017 err = netxen_init_firmware(adapter); 1148 err = netxen_nic_attach(adapter);
1018 if (err != 0) { 1149 if (err)
1019 printk(KERN_ERR "Failed to init firmware\n");
1020 return -EIO;
1021 }
1022
1023 if (adapter->fw_major < 4)
1024 adapter->max_rds_rings = 3;
1025 else
1026 adapter->max_rds_rings = 2;
1027
1028 err = netxen_alloc_sw_resources(adapter);
1029 if (err) {
1030 printk(KERN_ERR "%s: Error in setting sw resources\n",
1031 netdev->name);
1032 return err; 1150 return err;
1033 }
1034
1035 netxen_nic_clear_stats(adapter);
1036
1037 err = netxen_alloc_hw_resources(adapter);
1038 if (err) {
1039 printk(KERN_ERR "%s: Error in setting hw resources\n",
1040 netdev->name);
1041 goto err_out_free_sw;
1042 }
1043
1044 if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) ||
1045 (adapter->intr_scheme != INTR_SCHEME_PERPORT)) {
1046 printk(KERN_ERR "%s: Firmware interrupt scheme is "
1047 "incompatible with driver\n",
1048 netdev->name);
1049 adapter->driver_mismatch = 1;
1050 goto err_out_free_hw;
1051 }
1052
1053 if (adapter->fw_major < 4) {
1054 adapter->crb_addr_cmd_producer =
1055 crb_cmd_producer[adapter->portnum];
1056 adapter->crb_addr_cmd_consumer =
1057 crb_cmd_consumer[adapter->portnum];
1058
1059 netxen_nic_update_cmd_producer(adapter, 0);
1060 netxen_nic_update_cmd_consumer(adapter, 0);
1061 }
1062
1063 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
1064 for (ring = 0; ring < adapter->max_rds_rings; ring++)
1065 netxen_post_rx_buffers(adapter, ctx, ring);
1066 }
1067 if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
1068 handler = netxen_msix_intr;
1069 else if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
1070 handler = netxen_msi_intr;
1071 else {
1072 flags |= IRQF_SHARED;
1073 handler = netxen_intr;
1074 }
1075 adapter->irq = netdev->irq;
1076 err = request_irq(adapter->irq, handler,
1077 flags, netdev->name, adapter);
1078 if (err) {
1079 printk(KERN_ERR "request_irq failed with: %d\n", err);
1080 goto err_out_free_rxbuf;
1081 }
1082
1083 adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
1084 } 1151 }
1085 1152
1086 /* Done here again so that even if phantom sw overwrote it, 1153 err = netxen_nic_up(adapter, netdev);
1087 * we set it */ 1154 if (err)
1088 err = adapter->init_port(adapter, adapter->physical_port); 1155 goto err_out;
1089 if (err) {
1090 printk(KERN_ERR "%s: Failed to initialize port %d\n",
1091 netxen_nic_driver_name, adapter->portnum);
1092 goto err_out_free_irq;
1093 }
1094 adapter->macaddr_set(adapter, netdev->dev_addr);
1095
1096 netxen_nic_set_link_parameters(adapter);
1097
1098 netxen_set_multicast_list(netdev);
1099 if (adapter->set_mtu)
1100 adapter->set_mtu(adapter, netdev->mtu);
1101
1102 adapter->ahw.linkup = 0;
1103 mod_timer(&adapter->watchdog_timer, jiffies);
1104
1105 napi_enable(&adapter->napi);
1106 netxen_nic_enable_int(adapter);
1107 1156
1108 netif_start_queue(netdev); 1157 netif_start_queue(netdev);
1109 1158
1110 return 0; 1159 return 0;
1111 1160
1112err_out_free_irq: 1161err_out:
1113 free_irq(adapter->irq, adapter); 1162 netxen_nic_detach(adapter);
1114err_out_free_rxbuf:
1115 netxen_release_rx_buffers(adapter);
1116err_out_free_hw:
1117 netxen_free_hw_resources(adapter);
1118err_out_free_sw:
1119 netxen_free_sw_resources(adapter);
1120 return err; 1163 return err;
1121} 1164}
1122 1165
@@ -1127,20 +1170,7 @@ static int netxen_nic_close(struct net_device *netdev)
1127{ 1170{
1128 struct netxen_adapter *adapter = netdev_priv(netdev); 1171 struct netxen_adapter *adapter = netdev_priv(netdev);
1129 1172
1130 netif_carrier_off(netdev); 1173 netxen_nic_down(adapter, netdev);
1131 netif_stop_queue(netdev);
1132 napi_disable(&adapter->napi);
1133
1134 if (adapter->stop_port)
1135 adapter->stop_port(adapter);
1136
1137 netxen_nic_disable_int(adapter);
1138
1139 netxen_release_tx_buffers(adapter);
1140
1141 FLUSH_SCHEDULED_WORK();
1142 del_timer_sync(&adapter->watchdog_timer);
1143
1144 return 0; 1174 return 0;
1145} 1175}
1146 1176