aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorPaul Fulghum <paulkf@microgate.com>2010-10-27 18:34:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-27 21:03:14 -0400
commitffd7d6baa65e6161cfd996a59d55c48571c2a5f3 (patch)
treed54651c55afcdc57a23b6aae48782b616219f2e3 /drivers/char
parentdcade5ed16cce572e375bf4e63dd2150c351bf49 (diff)
synclink_gt: fix per device locking
Fix a long standing bug with per device locking. Each device has an associated spinlock for synchronizing access to hardware and state information with the ISR. A single hardware card has one or more devices. Bug: Non ISR code correctly acquires and releases the per device lock. ISR incorrectly always acquires and releases the lock of the first device on the card. The decoupled and list based nature of the ISR and deferred processing interaction allowed this to work in normal operation. Exceptional events like an application forcing hardware shutdown, reset, or reconfiguration while active can trigger the bug. Fixed ISR to acquire and release the per device lock. One exception is manipulation of the GPIO card resource which is global and effectively owned by the first device of the card. Non-ISR access to GPIO resource is changed to use lock of first device on card. Signed-off-by: Paul Fulghum <paulkf@microgate.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/synclink_gt.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 1746d91205f7..11999784383e 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -2357,26 +2357,27 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
2357 2357
2358 DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level)); 2358 DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level));
2359 2359
2360 spin_lock(&info->lock);
2361
2362 while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { 2360 while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
2363 DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); 2361 DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
2364 info->irq_occurred = true; 2362 info->irq_occurred = true;
2365 for(i=0; i < info->port_count ; i++) { 2363 for(i=0; i < info->port_count ; i++) {
2366 if (info->port_array[i] == NULL) 2364 if (info->port_array[i] == NULL)
2367 continue; 2365 continue;
2366 spin_lock(&info->port_array[i]->lock);
2368 if (gsr & (BIT8 << i)) 2367 if (gsr & (BIT8 << i))
2369 isr_serial(info->port_array[i]); 2368 isr_serial(info->port_array[i]);
2370 if (gsr & (BIT16 << (i*2))) 2369 if (gsr & (BIT16 << (i*2)))
2371 isr_rdma(info->port_array[i]); 2370 isr_rdma(info->port_array[i]);
2372 if (gsr & (BIT17 << (i*2))) 2371 if (gsr & (BIT17 << (i*2)))
2373 isr_tdma(info->port_array[i]); 2372 isr_tdma(info->port_array[i]);
2373 spin_unlock(&info->port_array[i]->lock);
2374 } 2374 }
2375 } 2375 }
2376 2376
2377 if (info->gpio_present) { 2377 if (info->gpio_present) {
2378 unsigned int state; 2378 unsigned int state;
2379 unsigned int changed; 2379 unsigned int changed;
2380 spin_lock(&info->lock);
2380 while ((changed = rd_reg32(info, IOSR)) != 0) { 2381 while ((changed = rd_reg32(info, IOSR)) != 0) {
2381 DBGISR(("%s iosr=%08x\n", info->device_name, changed)); 2382 DBGISR(("%s iosr=%08x\n", info->device_name, changed));
2382 /* read latched state of GPIO signals */ 2383 /* read latched state of GPIO signals */
@@ -2388,22 +2389,24 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
2388 isr_gpio(info->port_array[i], changed, state); 2389 isr_gpio(info->port_array[i], changed, state);
2389 } 2390 }
2390 } 2391 }
2392 spin_unlock(&info->lock);
2391 } 2393 }
2392 2394
2393 for(i=0; i < info->port_count ; i++) { 2395 for(i=0; i < info->port_count ; i++) {
2394 struct slgt_info *port = info->port_array[i]; 2396 struct slgt_info *port = info->port_array[i];
2395 2397 if (port == NULL)
2396 if (port && (port->port.count || port->netcount) && 2398 continue;
2399 spin_lock(&port->lock);
2400 if ((port->port.count || port->netcount) &&
2397 port->pending_bh && !port->bh_running && 2401 port->pending_bh && !port->bh_running &&
2398 !port->bh_requested) { 2402 !port->bh_requested) {
2399 DBGISR(("%s bh queued\n", port->device_name)); 2403 DBGISR(("%s bh queued\n", port->device_name));
2400 schedule_work(&port->task); 2404 schedule_work(&port->task);
2401 port->bh_requested = true; 2405 port->bh_requested = true;
2402 } 2406 }
2407 spin_unlock(&port->lock);
2403 } 2408 }
2404 2409
2405 spin_unlock(&info->lock);
2406
2407 DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level)); 2410 DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level));
2408 return IRQ_HANDLED; 2411 return IRQ_HANDLED;
2409} 2412}
@@ -2906,7 +2909,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
2906 info->device_name, gpio.state, gpio.smask, 2909 info->device_name, gpio.state, gpio.smask,
2907 gpio.dir, gpio.dmask)); 2910 gpio.dir, gpio.dmask));
2908 2911
2909 spin_lock_irqsave(&info->lock,flags); 2912 spin_lock_irqsave(&info->port_array[0]->lock, flags);
2910 if (gpio.dmask) { 2913 if (gpio.dmask) {
2911 data = rd_reg32(info, IODR); 2914 data = rd_reg32(info, IODR);
2912 data |= gpio.dmask & gpio.dir; 2915 data |= gpio.dmask & gpio.dir;
@@ -2919,7 +2922,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
2919 data &= ~(gpio.smask & ~gpio.state); 2922 data &= ~(gpio.smask & ~gpio.state);
2920 wr_reg32(info, IOVR, data); 2923 wr_reg32(info, IOVR, data);
2921 } 2924 }
2922 spin_unlock_irqrestore(&info->lock,flags); 2925 spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
2923 2926
2924 return 0; 2927 return 0;
2925} 2928}
@@ -3020,7 +3023,7 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
3020 return -EINVAL; 3023 return -EINVAL;
3021 init_cond_wait(&wait, gpio.smask); 3024 init_cond_wait(&wait, gpio.smask);
3022 3025
3023 spin_lock_irqsave(&info->lock, flags); 3026 spin_lock_irqsave(&info->port_array[0]->lock, flags);
3024 /* enable interrupts for watched pins */ 3027 /* enable interrupts for watched pins */
3025 wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); 3028 wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask);
3026 /* get current pin states */ 3029 /* get current pin states */
@@ -3032,20 +3035,20 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
3032 } else { 3035 } else {
3033 /* wait for target state */ 3036 /* wait for target state */
3034 add_cond_wait(&info->gpio_wait_q, &wait); 3037 add_cond_wait(&info->gpio_wait_q, &wait);
3035 spin_unlock_irqrestore(&info->lock, flags); 3038 spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
3036 schedule(); 3039 schedule();
3037 if (signal_pending(current)) 3040 if (signal_pending(current))
3038 rc = -ERESTARTSYS; 3041 rc = -ERESTARTSYS;
3039 else 3042 else
3040 gpio.state = wait.data; 3043 gpio.state = wait.data;
3041 spin_lock_irqsave(&info->lock, flags); 3044 spin_lock_irqsave(&info->port_array[0]->lock, flags);
3042 remove_cond_wait(&info->gpio_wait_q, &wait); 3045 remove_cond_wait(&info->gpio_wait_q, &wait);
3043 } 3046 }
3044 3047
3045 /* disable all GPIO interrupts if no waiting processes */ 3048 /* disable all GPIO interrupts if no waiting processes */
3046 if (info->gpio_wait_q == NULL) 3049 if (info->gpio_wait_q == NULL)
3047 wr_reg32(info, IOER, 0); 3050 wr_reg32(info, IOER, 0);
3048 spin_unlock_irqrestore(&info->lock,flags); 3051 spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
3049 3052
3050 if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) 3053 if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio)))
3051 rc = -EFAULT; 3054 rc = -EFAULT;
@@ -3578,7 +3581,6 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
3578 3581
3579 /* copy resource information from first port to others */ 3582 /* copy resource information from first port to others */
3580 for (i = 1; i < port_count; ++i) { 3583 for (i = 1; i < port_count; ++i) {
3581 port_array[i]->lock = port_array[0]->lock;
3582 port_array[i]->irq_level = port_array[0]->irq_level; 3584 port_array[i]->irq_level = port_array[0]->irq_level;
3583 port_array[i]->reg_addr = port_array[0]->reg_addr; 3585 port_array[i]->reg_addr = port_array[0]->reg_addr;
3584 alloc_dma_bufs(port_array[i]); 3586 alloc_dma_bufs(port_array[i]);