diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-29 10:43:16 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-29 10:43:16 -0400 |
commit | 78283dd29e647775cb1e63a4d6554b3090b9a9ff (patch) | |
tree | 46a179781ed356c0546379ecc46ca5daed7ae50a /drivers/block/rsxx/core.c | |
parent | 435932f2c75efcdd07273a437b9be32647d56d73 (diff) | |
parent | 5ae90d8e467e625e447000cb4335c4db973b1095 (diff) |
Merge 3.11-rc3 into usb-next
Diffstat (limited to 'drivers/block/rsxx/core.c')
-rw-r--r-- | drivers/block/rsxx/core.c | 359 |
1 files changed, 348 insertions, 11 deletions
diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c index 5af21f2db29c..6e85e21445eb 100644 --- a/drivers/block/rsxx/core.c +++ b/drivers/block/rsxx/core.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/debugfs.h> | ||
35 | #include <linux/seq_file.h> | ||
34 | 36 | ||
35 | #include <linux/genhd.h> | 37 | #include <linux/genhd.h> |
36 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
@@ -39,8 +41,9 @@ | |||
39 | #include "rsxx_cfg.h" | 41 | #include "rsxx_cfg.h" |
40 | 42 | ||
41 | #define NO_LEGACY 0 | 43 | #define NO_LEGACY 0 |
44 | #define SYNC_START_TIMEOUT (10 * 60) /* 10 minutes */ | ||
42 | 45 | ||
43 | MODULE_DESCRIPTION("IBM FlashSystem 70/80 PCIe SSD Device Driver"); | 46 | MODULE_DESCRIPTION("IBM Flash Adapter 900GB Full Height Device Driver"); |
44 | MODULE_AUTHOR("Joshua Morris/Philip Kelleher, IBM"); | 47 | MODULE_AUTHOR("Joshua Morris/Philip Kelleher, IBM"); |
45 | MODULE_LICENSE("GPL"); | 48 | MODULE_LICENSE("GPL"); |
46 | MODULE_VERSION(DRIVER_VERSION); | 49 | MODULE_VERSION(DRIVER_VERSION); |
@@ -49,9 +52,282 @@ static unsigned int force_legacy = NO_LEGACY; | |||
49 | module_param(force_legacy, uint, 0444); | 52 | module_param(force_legacy, uint, 0444); |
50 | MODULE_PARM_DESC(force_legacy, "Force the use of legacy type PCI interrupts"); | 53 | MODULE_PARM_DESC(force_legacy, "Force the use of legacy type PCI interrupts"); |
51 | 54 | ||
55 | static unsigned int sync_start = 1; | ||
56 | module_param(sync_start, uint, 0444); | ||
57 | MODULE_PARM_DESC(sync_start, "On by Default: Driver load will not complete " | ||
58 | "until the card startup has completed."); | ||
59 | |||
52 | static DEFINE_IDA(rsxx_disk_ida); | 60 | static DEFINE_IDA(rsxx_disk_ida); |
53 | static DEFINE_SPINLOCK(rsxx_ida_lock); | 61 | static DEFINE_SPINLOCK(rsxx_ida_lock); |
54 | 62 | ||
63 | /* --------------------Debugfs Setup ------------------- */ | ||
64 | |||
65 | struct rsxx_cram { | ||
66 | u32 f_pos; | ||
67 | u32 offset; | ||
68 | void *i_private; | ||
69 | }; | ||
70 | |||
71 | static int rsxx_attr_pci_regs_show(struct seq_file *m, void *p) | ||
72 | { | ||
73 | struct rsxx_cardinfo *card = m->private; | ||
74 | |||
75 | seq_printf(m, "HWID 0x%08x\n", | ||
76 | ioread32(card->regmap + HWID)); | ||
77 | seq_printf(m, "SCRATCH 0x%08x\n", | ||
78 | ioread32(card->regmap + SCRATCH)); | ||
79 | seq_printf(m, "IER 0x%08x\n", | ||
80 | ioread32(card->regmap + IER)); | ||
81 | seq_printf(m, "IPR 0x%08x\n", | ||
82 | ioread32(card->regmap + IPR)); | ||
83 | seq_printf(m, "CREG_CMD 0x%08x\n", | ||
84 | ioread32(card->regmap + CREG_CMD)); | ||
85 | seq_printf(m, "CREG_ADD 0x%08x\n", | ||
86 | ioread32(card->regmap + CREG_ADD)); | ||
87 | seq_printf(m, "CREG_CNT 0x%08x\n", | ||
88 | ioread32(card->regmap + CREG_CNT)); | ||
89 | seq_printf(m, "CREG_STAT 0x%08x\n", | ||
90 | ioread32(card->regmap + CREG_STAT)); | ||
91 | seq_printf(m, "CREG_DATA0 0x%08x\n", | ||
92 | ioread32(card->regmap + CREG_DATA0)); | ||
93 | seq_printf(m, "CREG_DATA1 0x%08x\n", | ||
94 | ioread32(card->regmap + CREG_DATA1)); | ||
95 | seq_printf(m, "CREG_DATA2 0x%08x\n", | ||
96 | ioread32(card->regmap + CREG_DATA2)); | ||
97 | seq_printf(m, "CREG_DATA3 0x%08x\n", | ||
98 | ioread32(card->regmap + CREG_DATA3)); | ||
99 | seq_printf(m, "CREG_DATA4 0x%08x\n", | ||
100 | ioread32(card->regmap + CREG_DATA4)); | ||
101 | seq_printf(m, "CREG_DATA5 0x%08x\n", | ||
102 | ioread32(card->regmap + CREG_DATA5)); | ||
103 | seq_printf(m, "CREG_DATA6 0x%08x\n", | ||
104 | ioread32(card->regmap + CREG_DATA6)); | ||
105 | seq_printf(m, "CREG_DATA7 0x%08x\n", | ||
106 | ioread32(card->regmap + CREG_DATA7)); | ||
107 | seq_printf(m, "INTR_COAL 0x%08x\n", | ||
108 | ioread32(card->regmap + INTR_COAL)); | ||
109 | seq_printf(m, "HW_ERROR 0x%08x\n", | ||
110 | ioread32(card->regmap + HW_ERROR)); | ||
111 | seq_printf(m, "DEBUG0 0x%08x\n", | ||
112 | ioread32(card->regmap + PCI_DEBUG0)); | ||
113 | seq_printf(m, "DEBUG1 0x%08x\n", | ||
114 | ioread32(card->regmap + PCI_DEBUG1)); | ||
115 | seq_printf(m, "DEBUG2 0x%08x\n", | ||
116 | ioread32(card->regmap + PCI_DEBUG2)); | ||
117 | seq_printf(m, "DEBUG3 0x%08x\n", | ||
118 | ioread32(card->regmap + PCI_DEBUG3)); | ||
119 | seq_printf(m, "DEBUG4 0x%08x\n", | ||
120 | ioread32(card->regmap + PCI_DEBUG4)); | ||
121 | seq_printf(m, "DEBUG5 0x%08x\n", | ||
122 | ioread32(card->regmap + PCI_DEBUG5)); | ||
123 | seq_printf(m, "DEBUG6 0x%08x\n", | ||
124 | ioread32(card->regmap + PCI_DEBUG6)); | ||
125 | seq_printf(m, "DEBUG7 0x%08x\n", | ||
126 | ioread32(card->regmap + PCI_DEBUG7)); | ||
127 | seq_printf(m, "RECONFIG 0x%08x\n", | ||
128 | ioread32(card->regmap + PCI_RECONFIG)); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int rsxx_attr_stats_show(struct seq_file *m, void *p) | ||
134 | { | ||
135 | struct rsxx_cardinfo *card = m->private; | ||
136 | int i; | ||
137 | |||
138 | for (i = 0; i < card->n_targets; i++) { | ||
139 | seq_printf(m, "Ctrl %d CRC Errors = %d\n", | ||
140 | i, card->ctrl[i].stats.crc_errors); | ||
141 | seq_printf(m, "Ctrl %d Hard Errors = %d\n", | ||
142 | i, card->ctrl[i].stats.hard_errors); | ||
143 | seq_printf(m, "Ctrl %d Soft Errors = %d\n", | ||
144 | i, card->ctrl[i].stats.soft_errors); | ||
145 | seq_printf(m, "Ctrl %d Writes Issued = %d\n", | ||
146 | i, card->ctrl[i].stats.writes_issued); | ||
147 | seq_printf(m, "Ctrl %d Writes Failed = %d\n", | ||
148 | i, card->ctrl[i].stats.writes_failed); | ||
149 | seq_printf(m, "Ctrl %d Reads Issued = %d\n", | ||
150 | i, card->ctrl[i].stats.reads_issued); | ||
151 | seq_printf(m, "Ctrl %d Reads Failed = %d\n", | ||
152 | i, card->ctrl[i].stats.reads_failed); | ||
153 | seq_printf(m, "Ctrl %d Reads Retried = %d\n", | ||
154 | i, card->ctrl[i].stats.reads_retried); | ||
155 | seq_printf(m, "Ctrl %d Discards Issued = %d\n", | ||
156 | i, card->ctrl[i].stats.discards_issued); | ||
157 | seq_printf(m, "Ctrl %d Discards Failed = %d\n", | ||
158 | i, card->ctrl[i].stats.discards_failed); | ||
159 | seq_printf(m, "Ctrl %d DMA SW Errors = %d\n", | ||
160 | i, card->ctrl[i].stats.dma_sw_err); | ||
161 | seq_printf(m, "Ctrl %d DMA HW Faults = %d\n", | ||
162 | i, card->ctrl[i].stats.dma_hw_fault); | ||
163 | seq_printf(m, "Ctrl %d DMAs Cancelled = %d\n", | ||
164 | i, card->ctrl[i].stats.dma_cancelled); | ||
165 | seq_printf(m, "Ctrl %d SW Queue Depth = %d\n", | ||
166 | i, card->ctrl[i].stats.sw_q_depth); | ||
167 | seq_printf(m, "Ctrl %d HW Queue Depth = %d\n", | ||
168 | i, atomic_read(&card->ctrl[i].stats.hw_q_depth)); | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int rsxx_attr_stats_open(struct inode *inode, struct file *file) | ||
175 | { | ||
176 | return single_open(file, rsxx_attr_stats_show, inode->i_private); | ||
177 | } | ||
178 | |||
179 | static int rsxx_attr_pci_regs_open(struct inode *inode, struct file *file) | ||
180 | { | ||
181 | return single_open(file, rsxx_attr_pci_regs_show, inode->i_private); | ||
182 | } | ||
183 | |||
184 | static ssize_t rsxx_cram_read(struct file *fp, char __user *ubuf, | ||
185 | size_t cnt, loff_t *ppos) | ||
186 | { | ||
187 | struct rsxx_cram *info = fp->private_data; | ||
188 | struct rsxx_cardinfo *card = info->i_private; | ||
189 | char *buf; | ||
190 | int st; | ||
191 | |||
192 | buf = kzalloc(sizeof(*buf) * cnt, GFP_KERNEL); | ||
193 | if (!buf) | ||
194 | return -ENOMEM; | ||
195 | |||
196 | info->f_pos = (u32)*ppos + info->offset; | ||
197 | |||
198 | st = rsxx_creg_read(card, CREG_ADD_CRAM + info->f_pos, cnt, buf, 1); | ||
199 | if (st) | ||
200 | return st; | ||
201 | |||
202 | st = copy_to_user(ubuf, buf, cnt); | ||
203 | if (st) | ||
204 | return st; | ||
205 | |||
206 | info->offset += cnt; | ||
207 | |||
208 | kfree(buf); | ||
209 | |||
210 | return cnt; | ||
211 | } | ||
212 | |||
213 | static ssize_t rsxx_cram_write(struct file *fp, const char __user *ubuf, | ||
214 | size_t cnt, loff_t *ppos) | ||
215 | { | ||
216 | struct rsxx_cram *info = fp->private_data; | ||
217 | struct rsxx_cardinfo *card = info->i_private; | ||
218 | char *buf; | ||
219 | int st; | ||
220 | |||
221 | buf = kzalloc(sizeof(*buf) * cnt, GFP_KERNEL); | ||
222 | if (!buf) | ||
223 | return -ENOMEM; | ||
224 | |||
225 | st = copy_from_user(buf, ubuf, cnt); | ||
226 | if (st) | ||
227 | return st; | ||
228 | |||
229 | info->f_pos = (u32)*ppos + info->offset; | ||
230 | |||
231 | st = rsxx_creg_write(card, CREG_ADD_CRAM + info->f_pos, cnt, buf, 1); | ||
232 | if (st) | ||
233 | return st; | ||
234 | |||
235 | info->offset += cnt; | ||
236 | |||
237 | kfree(buf); | ||
238 | |||
239 | return cnt; | ||
240 | } | ||
241 | |||
242 | static int rsxx_cram_open(struct inode *inode, struct file *file) | ||
243 | { | ||
244 | struct rsxx_cram *info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
245 | if (!info) | ||
246 | return -ENOMEM; | ||
247 | |||
248 | info->i_private = inode->i_private; | ||
249 | info->f_pos = file->f_pos; | ||
250 | file->private_data = info; | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static int rsxx_cram_release(struct inode *inode, struct file *file) | ||
256 | { | ||
257 | struct rsxx_cram *info = file->private_data; | ||
258 | |||
259 | if (!info) | ||
260 | return 0; | ||
261 | |||
262 | kfree(info); | ||
263 | file->private_data = NULL; | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static const struct file_operations debugfs_cram_fops = { | ||
269 | .owner = THIS_MODULE, | ||
270 | .open = rsxx_cram_open, | ||
271 | .read = rsxx_cram_read, | ||
272 | .write = rsxx_cram_write, | ||
273 | .release = rsxx_cram_release, | ||
274 | }; | ||
275 | |||
276 | static const struct file_operations debugfs_stats_fops = { | ||
277 | .owner = THIS_MODULE, | ||
278 | .open = rsxx_attr_stats_open, | ||
279 | .read = seq_read, | ||
280 | .llseek = seq_lseek, | ||
281 | .release = single_release, | ||
282 | }; | ||
283 | |||
284 | static const struct file_operations debugfs_pci_regs_fops = { | ||
285 | .owner = THIS_MODULE, | ||
286 | .open = rsxx_attr_pci_regs_open, | ||
287 | .read = seq_read, | ||
288 | .llseek = seq_lseek, | ||
289 | .release = single_release, | ||
290 | }; | ||
291 | |||
292 | static void rsxx_debugfs_dev_new(struct rsxx_cardinfo *card) | ||
293 | { | ||
294 | struct dentry *debugfs_stats; | ||
295 | struct dentry *debugfs_pci_regs; | ||
296 | struct dentry *debugfs_cram; | ||
297 | |||
298 | card->debugfs_dir = debugfs_create_dir(card->gendisk->disk_name, NULL); | ||
299 | if (IS_ERR_OR_NULL(card->debugfs_dir)) | ||
300 | goto failed_debugfs_dir; | ||
301 | |||
302 | debugfs_stats = debugfs_create_file("stats", S_IRUGO, | ||
303 | card->debugfs_dir, card, | ||
304 | &debugfs_stats_fops); | ||
305 | if (IS_ERR_OR_NULL(debugfs_stats)) | ||
306 | goto failed_debugfs_stats; | ||
307 | |||
308 | debugfs_pci_regs = debugfs_create_file("pci_regs", S_IRUGO, | ||
309 | card->debugfs_dir, card, | ||
310 | &debugfs_pci_regs_fops); | ||
311 | if (IS_ERR_OR_NULL(debugfs_pci_regs)) | ||
312 | goto failed_debugfs_pci_regs; | ||
313 | |||
314 | debugfs_cram = debugfs_create_file("cram", S_IRUGO | S_IWUSR, | ||
315 | card->debugfs_dir, card, | ||
316 | &debugfs_cram_fops); | ||
317 | if (IS_ERR_OR_NULL(debugfs_cram)) | ||
318 | goto failed_debugfs_cram; | ||
319 | |||
320 | return; | ||
321 | failed_debugfs_cram: | ||
322 | debugfs_remove(debugfs_pci_regs); | ||
323 | failed_debugfs_pci_regs: | ||
324 | debugfs_remove(debugfs_stats); | ||
325 | failed_debugfs_stats: | ||
326 | debugfs_remove(card->debugfs_dir); | ||
327 | failed_debugfs_dir: | ||
328 | card->debugfs_dir = NULL; | ||
329 | } | ||
330 | |||
55 | /*----------------- Interrupt Control & Handling -------------------*/ | 331 | /*----------------- Interrupt Control & Handling -------------------*/ |
56 | 332 | ||
57 | static void rsxx_mask_interrupts(struct rsxx_cardinfo *card) | 333 | static void rsxx_mask_interrupts(struct rsxx_cardinfo *card) |
@@ -163,12 +439,13 @@ static irqreturn_t rsxx_isr(int irq, void *pdata) | |||
163 | } | 439 | } |
164 | 440 | ||
165 | if (isr & CR_INTR_CREG) { | 441 | if (isr & CR_INTR_CREG) { |
166 | schedule_work(&card->creg_ctrl.done_work); | 442 | queue_work(card->creg_ctrl.creg_wq, |
443 | &card->creg_ctrl.done_work); | ||
167 | handled++; | 444 | handled++; |
168 | } | 445 | } |
169 | 446 | ||
170 | if (isr & CR_INTR_EVENT) { | 447 | if (isr & CR_INTR_EVENT) { |
171 | schedule_work(&card->event_work); | 448 | queue_work(card->event_wq, &card->event_work); |
172 | rsxx_disable_ier_and_isr(card, CR_INTR_EVENT); | 449 | rsxx_disable_ier_and_isr(card, CR_INTR_EVENT); |
173 | handled++; | 450 | handled++; |
174 | } | 451 | } |
@@ -329,7 +606,7 @@ static int rsxx_eeh_frozen(struct pci_dev *dev) | |||
329 | int i; | 606 | int i; |
330 | int st; | 607 | int st; |
331 | 608 | ||
332 | dev_warn(&dev->dev, "IBM FlashSystem PCI: preparing for slot reset.\n"); | 609 | dev_warn(&dev->dev, "IBM Flash Adapter PCI: preparing for slot reset.\n"); |
333 | 610 | ||
334 | card->eeh_state = 1; | 611 | card->eeh_state = 1; |
335 | rsxx_mask_interrupts(card); | 612 | rsxx_mask_interrupts(card); |
@@ -367,15 +644,26 @@ static void rsxx_eeh_failure(struct pci_dev *dev) | |||
367 | { | 644 | { |
368 | struct rsxx_cardinfo *card = pci_get_drvdata(dev); | 645 | struct rsxx_cardinfo *card = pci_get_drvdata(dev); |
369 | int i; | 646 | int i; |
647 | int cnt = 0; | ||
370 | 648 | ||
371 | dev_err(&dev->dev, "IBM FlashSystem PCI: disabling failed card.\n"); | 649 | dev_err(&dev->dev, "IBM Flash Adapter PCI: disabling failed card.\n"); |
372 | 650 | ||
373 | card->eeh_state = 1; | 651 | card->eeh_state = 1; |
652 | card->halt = 1; | ||
374 | 653 | ||
375 | for (i = 0; i < card->n_targets; i++) | 654 | for (i = 0; i < card->n_targets; i++) { |
376 | del_timer_sync(&card->ctrl[i].activity_timer); | 655 | spin_lock_bh(&card->ctrl[i].queue_lock); |
656 | cnt = rsxx_cleanup_dma_queue(&card->ctrl[i], | ||
657 | &card->ctrl[i].queue); | ||
658 | spin_unlock_bh(&card->ctrl[i].queue_lock); | ||
659 | |||
660 | cnt += rsxx_dma_cancel(&card->ctrl[i]); | ||
377 | 661 | ||
378 | rsxx_eeh_cancel_dmas(card); | 662 | if (cnt) |
663 | dev_info(CARD_TO_DEV(card), | ||
664 | "Freed %d queued DMAs on channel %d\n", | ||
665 | cnt, card->ctrl[i].id); | ||
666 | } | ||
379 | } | 667 | } |
380 | 668 | ||
381 | static int rsxx_eeh_fifo_flush_poll(struct rsxx_cardinfo *card) | 669 | static int rsxx_eeh_fifo_flush_poll(struct rsxx_cardinfo *card) |
@@ -432,7 +720,7 @@ static pci_ers_result_t rsxx_slot_reset(struct pci_dev *dev) | |||
432 | int st; | 720 | int st; |
433 | 721 | ||
434 | dev_warn(&dev->dev, | 722 | dev_warn(&dev->dev, |
435 | "IBM FlashSystem PCI: recovering from slot reset.\n"); | 723 | "IBM Flash Adapter PCI: recovering from slot reset.\n"); |
436 | 724 | ||
437 | st = pci_enable_device(dev); | 725 | st = pci_enable_device(dev); |
438 | if (st) | 726 | if (st) |
@@ -485,7 +773,7 @@ static pci_ers_result_t rsxx_slot_reset(struct pci_dev *dev) | |||
485 | &card->ctrl[i].issue_dma_work); | 773 | &card->ctrl[i].issue_dma_work); |
486 | } | 774 | } |
487 | 775 | ||
488 | dev_info(&dev->dev, "IBM FlashSystem PCI: recovery complete.\n"); | 776 | dev_info(&dev->dev, "IBM Flash Adapter PCI: recovery complete.\n"); |
489 | 777 | ||
490 | return PCI_ERS_RESULT_RECOVERED; | 778 | return PCI_ERS_RESULT_RECOVERED; |
491 | 779 | ||
@@ -528,6 +816,7 @@ static int rsxx_pci_probe(struct pci_dev *dev, | |||
528 | { | 816 | { |
529 | struct rsxx_cardinfo *card; | 817 | struct rsxx_cardinfo *card; |
530 | int st; | 818 | int st; |
819 | unsigned int sync_timeout; | ||
531 | 820 | ||
532 | dev_info(&dev->dev, "PCI-Flash SSD discovered\n"); | 821 | dev_info(&dev->dev, "PCI-Flash SSD discovered\n"); |
533 | 822 | ||
@@ -610,7 +899,11 @@ static int rsxx_pci_probe(struct pci_dev *dev, | |||
610 | } | 899 | } |
611 | 900 | ||
612 | /************* Setup Processor Command Interface *************/ | 901 | /************* Setup Processor Command Interface *************/ |
613 | rsxx_creg_setup(card); | 902 | st = rsxx_creg_setup(card); |
903 | if (st) { | ||
904 | dev_err(CARD_TO_DEV(card), "Failed to setup creg interface.\n"); | ||
905 | goto failed_creg_setup; | ||
906 | } | ||
614 | 907 | ||
615 | spin_lock_irq(&card->irq_lock); | 908 | spin_lock_irq(&card->irq_lock); |
616 | rsxx_enable_ier_and_isr(card, CR_INTR_CREG); | 909 | rsxx_enable_ier_and_isr(card, CR_INTR_CREG); |
@@ -650,6 +943,12 @@ static int rsxx_pci_probe(struct pci_dev *dev, | |||
650 | } | 943 | } |
651 | 944 | ||
652 | /************* Setup Card Event Handler *************/ | 945 | /************* Setup Card Event Handler *************/ |
946 | card->event_wq = create_singlethread_workqueue(DRIVER_NAME"_event"); | ||
947 | if (!card->event_wq) { | ||
948 | dev_err(CARD_TO_DEV(card), "Failed card event setup.\n"); | ||
949 | goto failed_event_handler; | ||
950 | } | ||
951 | |||
653 | INIT_WORK(&card->event_work, card_event_handler); | 952 | INIT_WORK(&card->event_work, card_event_handler); |
654 | 953 | ||
655 | st = rsxx_setup_dev(card); | 954 | st = rsxx_setup_dev(card); |
@@ -676,6 +975,33 @@ static int rsxx_pci_probe(struct pci_dev *dev, | |||
676 | if (st) | 975 | if (st) |
677 | dev_crit(CARD_TO_DEV(card), | 976 | dev_crit(CARD_TO_DEV(card), |
678 | "Failed issuing card startup\n"); | 977 | "Failed issuing card startup\n"); |
978 | if (sync_start) { | ||
979 | sync_timeout = SYNC_START_TIMEOUT; | ||
980 | |||
981 | dev_info(CARD_TO_DEV(card), | ||
982 | "Waiting for card to startup\n"); | ||
983 | |||
984 | do { | ||
985 | ssleep(1); | ||
986 | sync_timeout--; | ||
987 | |||
988 | rsxx_get_card_state(card, &card->state); | ||
989 | } while (sync_timeout && | ||
990 | (card->state == CARD_STATE_STARTING)); | ||
991 | |||
992 | if (card->state == CARD_STATE_STARTING) { | ||
993 | dev_warn(CARD_TO_DEV(card), | ||
994 | "Card startup timed out\n"); | ||
995 | card->size8 = 0; | ||
996 | } else { | ||
997 | dev_info(CARD_TO_DEV(card), | ||
998 | "card state: %s\n", | ||
999 | rsxx_card_state_to_str(card->state)); | ||
1000 | st = rsxx_get_card_size8(card, &card->size8); | ||
1001 | if (st) | ||
1002 | card->size8 = 0; | ||
1003 | } | ||
1004 | } | ||
679 | } else if (card->state == CARD_STATE_GOOD || | 1005 | } else if (card->state == CARD_STATE_GOOD || |
680 | card->state == CARD_STATE_RD_ONLY_FAULT) { | 1006 | card->state == CARD_STATE_RD_ONLY_FAULT) { |
681 | st = rsxx_get_card_size8(card, &card->size8); | 1007 | st = rsxx_get_card_size8(card, &card->size8); |
@@ -685,12 +1011,21 @@ static int rsxx_pci_probe(struct pci_dev *dev, | |||
685 | 1011 | ||
686 | rsxx_attach_dev(card); | 1012 | rsxx_attach_dev(card); |
687 | 1013 | ||
1014 | /************* Setup Debugfs *************/ | ||
1015 | rsxx_debugfs_dev_new(card); | ||
1016 | |||
688 | return 0; | 1017 | return 0; |
689 | 1018 | ||
690 | failed_create_dev: | 1019 | failed_create_dev: |
1020 | destroy_workqueue(card->event_wq); | ||
1021 | card->event_wq = NULL; | ||
1022 | failed_event_handler: | ||
691 | rsxx_dma_destroy(card); | 1023 | rsxx_dma_destroy(card); |
692 | failed_dma_setup: | 1024 | failed_dma_setup: |
693 | failed_compatiblity_check: | 1025 | failed_compatiblity_check: |
1026 | destroy_workqueue(card->creg_ctrl.creg_wq); | ||
1027 | card->creg_ctrl.creg_wq = NULL; | ||
1028 | failed_creg_setup: | ||
694 | spin_lock_irq(&card->irq_lock); | 1029 | spin_lock_irq(&card->irq_lock); |
695 | rsxx_disable_ier_and_isr(card, CR_INTR_ALL); | 1030 | rsxx_disable_ier_and_isr(card, CR_INTR_ALL); |
696 | spin_unlock_irq(&card->irq_lock); | 1031 | spin_unlock_irq(&card->irq_lock); |
@@ -756,6 +1091,8 @@ static void rsxx_pci_remove(struct pci_dev *dev) | |||
756 | /* Prevent work_structs from re-queuing themselves. */ | 1091 | /* Prevent work_structs from re-queuing themselves. */ |
757 | card->halt = 1; | 1092 | card->halt = 1; |
758 | 1093 | ||
1094 | debugfs_remove_recursive(card->debugfs_dir); | ||
1095 | |||
759 | free_irq(dev->irq, card); | 1096 | free_irq(dev->irq, card); |
760 | 1097 | ||
761 | if (!force_legacy) | 1098 | if (!force_legacy) |