diff options
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/ioat.c | 92 |
1 files changed, 34 insertions, 58 deletions
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c index 9b16a3af9a0a..4105d6575b64 100644 --- a/drivers/dma/ioat.c +++ b/drivers/dma/ioat.c | |||
@@ -75,60 +75,10 @@ static int ioat_dca_enabled = 1; | |||
75 | module_param(ioat_dca_enabled, int, 0644); | 75 | module_param(ioat_dca_enabled, int, 0644); |
76 | MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)"); | 76 | MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)"); |
77 | 77 | ||
78 | static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase) | ||
79 | { | ||
80 | struct ioat_device *device = pci_get_drvdata(pdev); | ||
81 | u8 version; | ||
82 | int err = 0; | ||
83 | |||
84 | version = readb(iobase + IOAT_VER_OFFSET); | ||
85 | switch (version) { | ||
86 | case IOAT_VER_1_2: | ||
87 | device->dma = ioat_dma_probe(pdev, iobase); | ||
88 | if (device->dma && ioat_dca_enabled) | ||
89 | device->dca = ioat_dca_init(pdev, iobase); | ||
90 | break; | ||
91 | case IOAT_VER_2_0: | ||
92 | device->dma = ioat_dma_probe(pdev, iobase); | ||
93 | if (device->dma && ioat_dca_enabled) | ||
94 | device->dca = ioat2_dca_init(pdev, iobase); | ||
95 | break; | ||
96 | case IOAT_VER_3_0: | ||
97 | device->dma = ioat_dma_probe(pdev, iobase); | ||
98 | if (device->dma && ioat_dca_enabled) | ||
99 | device->dca = ioat3_dca_init(pdev, iobase); | ||
100 | break; | ||
101 | default: | ||
102 | err = -ENODEV; | ||
103 | break; | ||
104 | } | ||
105 | if (!device->dma) | ||
106 | err = -ENODEV; | ||
107 | return err; | ||
108 | } | ||
109 | |||
110 | static void ioat_shutdown_functionality(struct pci_dev *pdev) | ||
111 | { | ||
112 | struct ioat_device *device = pci_get_drvdata(pdev); | ||
113 | |||
114 | dev_err(&pdev->dev, "Removing dma and dca services\n"); | ||
115 | if (device->dca) { | ||
116 | unregister_dca_provider(device->dca); | ||
117 | free_dca_provider(device->dca); | ||
118 | device->dca = NULL; | ||
119 | } | ||
120 | |||
121 | if (device->dma) { | ||
122 | ioat_dma_remove(device->dma); | ||
123 | device->dma = NULL; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | static struct pci_driver ioat_pci_driver = { | 78 | static struct pci_driver ioat_pci_driver = { |
128 | .name = "ioatdma", | 79 | .name = "ioatdma", |
129 | .id_table = ioat_pci_tbl, | 80 | .id_table = ioat_pci_tbl, |
130 | .probe = ioat_probe, | 81 | .probe = ioat_probe, |
131 | .shutdown = ioat_shutdown_functionality, | ||
132 | .remove = __devexit_p(ioat_remove), | 82 | .remove = __devexit_p(ioat_remove), |
133 | }; | 83 | }; |
134 | 84 | ||
@@ -179,7 +129,29 @@ static int __devinit ioat_probe(struct pci_dev *pdev, | |||
179 | 129 | ||
180 | pci_set_master(pdev); | 130 | pci_set_master(pdev); |
181 | 131 | ||
182 | err = ioat_setup_functionality(pdev, iobase); | 132 | switch (readb(iobase + IOAT_VER_OFFSET)) { |
133 | case IOAT_VER_1_2: | ||
134 | device->dma = ioat_dma_probe(pdev, iobase); | ||
135 | if (device->dma && ioat_dca_enabled) | ||
136 | device->dca = ioat_dca_init(pdev, iobase); | ||
137 | break; | ||
138 | case IOAT_VER_2_0: | ||
139 | device->dma = ioat_dma_probe(pdev, iobase); | ||
140 | if (device->dma && ioat_dca_enabled) | ||
141 | device->dca = ioat2_dca_init(pdev, iobase); | ||
142 | break; | ||
143 | case IOAT_VER_3_0: | ||
144 | device->dma = ioat_dma_probe(pdev, iobase); | ||
145 | if (device->dma && ioat_dca_enabled) | ||
146 | device->dca = ioat3_dca_init(pdev, iobase); | ||
147 | break; | ||
148 | default: | ||
149 | err = -ENODEV; | ||
150 | break; | ||
151 | } | ||
152 | if (!device->dma) | ||
153 | err = -ENODEV; | ||
154 | |||
183 | if (err) | 155 | if (err) |
184 | goto err_version; | 156 | goto err_version; |
185 | 157 | ||
@@ -198,17 +170,21 @@ err_enable_device: | |||
198 | return err; | 170 | return err; |
199 | } | 171 | } |
200 | 172 | ||
201 | /* | ||
202 | * It is unsafe to remove this module: if removed while a requested | ||
203 | * dma is outstanding, esp. from tcp, it is possible to hang while | ||
204 | * waiting for something that will never finish. However, if you're | ||
205 | * feeling lucky, this usually works just fine. | ||
206 | */ | ||
207 | static void __devexit ioat_remove(struct pci_dev *pdev) | 173 | static void __devexit ioat_remove(struct pci_dev *pdev) |
208 | { | 174 | { |
209 | struct ioat_device *device = pci_get_drvdata(pdev); | 175 | struct ioat_device *device = pci_get_drvdata(pdev); |
210 | 176 | ||
211 | ioat_shutdown_functionality(pdev); | 177 | dev_err(&pdev->dev, "Removing dma and dca services\n"); |
178 | if (device->dca) { | ||
179 | unregister_dca_provider(device->dca); | ||
180 | free_dca_provider(device->dca); | ||
181 | device->dca = NULL; | ||
182 | } | ||
183 | |||
184 | if (device->dma) { | ||
185 | ioat_dma_remove(device->dma); | ||
186 | device->dma = NULL; | ||
187 | } | ||
212 | 188 | ||
213 | kfree(device); | 189 | kfree(device); |
214 | } | 190 | } |