diff options
| -rw-r--r-- | Documentation/block/queue-sysfs.txt | 63 | ||||
| -rw-r--r-- | block/blk-core.c | 6 | ||||
| -rw-r--r-- | block/blk.h | 8 | ||||
| -rw-r--r-- | drivers/ide/Kconfig | 10 | ||||
| -rw-r--r-- | drivers/ide/Makefile | 1 | ||||
| -rw-r--r-- | drivers/ide/cs5536.c | 308 | ||||
| -rw-r--r-- | drivers/ide/icside.c | 2 | ||||
| -rw-r--r-- | drivers/ide/ide-acpi.c | 2 | ||||
| -rw-r--r-- | drivers/ide/ide-cd.c | 3 | ||||
| -rw-r--r-- | drivers/ide/ide-io.c | 9 | ||||
| -rw-r--r-- | drivers/ide/ide-probe.c | 43 | ||||
| -rw-r--r-- | drivers/ide/tx4939ide.c | 4 | ||||
| -rw-r--r-- | drivers/ide/via82cxxx.c | 5 | ||||
| -rw-r--r-- | drivers/usb/host/whci/asl.c | 9 | ||||
| -rw-r--r-- | drivers/usb/host/whci/hw.c | 15 | ||||
| -rw-r--r-- | drivers/usb/host/whci/pzl.c | 9 | ||||
| -rw-r--r-- | drivers/usb/host/whci/whcd.h | 1 | ||||
| -rw-r--r-- | drivers/usb/wusbcore/devconnect.c | 1 | ||||
| -rw-r--r-- | drivers/usb/wusbcore/rh.c | 3 | ||||
| -rw-r--r-- | drivers/uwb/allocator.c | 1 | ||||
| -rw-r--r-- | drivers/uwb/drp.c | 4 | ||||
| -rw-r--r-- | drivers/uwb/rsv.c | 21 | ||||
| -rw-r--r-- | drivers/virtio/virtio_pci.c | 2 | ||||
| -rw-r--r-- | include/linux/bio.h | 10 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 2 | ||||
| -rw-r--r-- | include/linux/module.h | 25 | ||||
| -rw-r--r-- | kernel/module.c | 35 |
27 files changed, 545 insertions, 57 deletions
diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt new file mode 100644 index 000000000000..e164403f60e1 --- /dev/null +++ b/Documentation/block/queue-sysfs.txt | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | Queue sysfs files | ||
| 2 | ================= | ||
| 3 | |||
| 4 | This text file will detail the queue files that are located in the sysfs tree | ||
| 5 | for each block device. Note that stacked devices typically do not export | ||
| 6 | any settings, since their queue merely functions are a remapping target. | ||
| 7 | These files are the ones found in the /sys/block/xxx/queue/ directory. | ||
| 8 | |||
| 9 | Files denoted with a RO postfix are readonly and the RW postfix means | ||
| 10 | read-write. | ||
| 11 | |||
| 12 | hw_sector_size (RO) | ||
| 13 | ------------------- | ||
| 14 | This is the hardware sector size of the device, in bytes. | ||
| 15 | |||
| 16 | max_hw_sectors_kb (RO) | ||
| 17 | ---------------------- | ||
| 18 | This is the maximum number of kilobytes supported in a single data transfer. | ||
| 19 | |||
| 20 | max_sectors_kb (RW) | ||
| 21 | ------------------- | ||
| 22 | This is the maximum number of kilobytes that the block layer will allow | ||
| 23 | for a filesystem request. Must be smaller than or equal to the maximum | ||
| 24 | size allowed by the hardware. | ||
| 25 | |||
| 26 | nomerges (RW) | ||
| 27 | ------------- | ||
| 28 | This enables the user to disable the lookup logic involved with IO merging | ||
| 29 | requests in the block layer. Merging may still occur through a direct | ||
| 30 | 1-hit cache, since that comes for (almost) free. The IO scheduler will not | ||
| 31 | waste cycles doing tree/hash lookups for merges if nomerges is 1. Defaults | ||
| 32 | to 0, enabling all merges. | ||
| 33 | |||
| 34 | nr_requests (RW) | ||
| 35 | ---------------- | ||
| 36 | This controls how many requests may be allocated in the block layer for | ||
| 37 | read or write requests. Note that the total allocated number may be twice | ||
| 38 | this amount, since it applies only to reads or writes (not the accumulated | ||
| 39 | sum). | ||
| 40 | |||
| 41 | read_ahead_kb (RW) | ||
| 42 | ------------------ | ||
| 43 | Maximum number of kilobytes to read-ahead for filesystems on this block | ||
| 44 | device. | ||
| 45 | |||
| 46 | rq_affinity (RW) | ||
| 47 | ---------------- | ||
| 48 | If this option is enabled, the block layer will migrate request completions | ||
| 49 | to the CPU that originally submitted the request. For some workloads | ||
| 50 | this provides a significant reduction in CPU cycles due to caching effects. | ||
| 51 | |||
| 52 | scheduler (RW) | ||
| 53 | -------------- | ||
| 54 | When read, this file will display the current and available IO schedulers | ||
| 55 | for this block device. The currently active IO scheduler will be enclosed | ||
| 56 | in [] brackets. Writing an IO scheduler name to this file will switch | ||
| 57 | control of this block device to that new IO scheduler. Note that writing | ||
| 58 | an IO scheduler name to this file will attempt to load that IO scheduler | ||
| 59 | module, if it isn't already present in the system. | ||
| 60 | |||
| 61 | |||
| 62 | |||
| 63 | Jens Axboe <jens.axboe@oracle.com>, February 2009 | ||
diff --git a/block/blk-core.c b/block/blk-core.c index ca69f3d94100..29bcfac6c688 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -69,7 +69,7 @@ static void drive_stat_acct(struct request *rq, int new_io) | |||
| 69 | int rw = rq_data_dir(rq); | 69 | int rw = rq_data_dir(rq); |
| 70 | int cpu; | 70 | int cpu; |
| 71 | 71 | ||
| 72 | if (!blk_fs_request(rq) || !disk || !blk_queue_io_stat(disk->queue)) | 72 | if (!blk_fs_request(rq) || !disk || !blk_do_io_stat(disk->queue)) |
| 73 | return; | 73 | return; |
| 74 | 74 | ||
| 75 | cpu = part_stat_lock(); | 75 | cpu = part_stat_lock(); |
| @@ -1667,7 +1667,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes) | |||
| 1667 | { | 1667 | { |
| 1668 | struct gendisk *disk = req->rq_disk; | 1668 | struct gendisk *disk = req->rq_disk; |
| 1669 | 1669 | ||
| 1670 | if (!disk || !blk_queue_io_stat(disk->queue)) | 1670 | if (!disk || !blk_do_io_stat(disk->queue)) |
| 1671 | return; | 1671 | return; |
| 1672 | 1672 | ||
| 1673 | if (blk_fs_request(req)) { | 1673 | if (blk_fs_request(req)) { |
| @@ -1686,7 +1686,7 @@ static void blk_account_io_done(struct request *req) | |||
| 1686 | { | 1686 | { |
| 1687 | struct gendisk *disk = req->rq_disk; | 1687 | struct gendisk *disk = req->rq_disk; |
| 1688 | 1688 | ||
| 1689 | if (!disk || !blk_queue_io_stat(disk->queue)) | 1689 | if (!disk || !blk_do_io_stat(disk->queue)) |
| 1690 | return; | 1690 | return; |
| 1691 | 1691 | ||
| 1692 | /* | 1692 | /* |
diff --git a/block/blk.h b/block/blk.h index 6e1ed40534e9..0dce92c37496 100644 --- a/block/blk.h +++ b/block/blk.h | |||
| @@ -108,4 +108,12 @@ static inline int blk_cpu_to_group(int cpu) | |||
| 108 | #endif | 108 | #endif |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | static inline int blk_do_io_stat(struct request_queue *q) | ||
| 112 | { | ||
| 113 | if (q) | ||
| 114 | return blk_queue_io_stat(q); | ||
| 115 | |||
| 116 | return 0; | ||
| 117 | } | ||
| 118 | |||
| 111 | #endif | 119 | #endif |
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index b1c6f68d98ce..3dad2299d9c5 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
| @@ -465,6 +465,16 @@ config BLK_DEV_CS5535 | |||
| 465 | 465 | ||
| 466 | It is safe to say Y to this question. | 466 | It is safe to say Y to this question. |
| 467 | 467 | ||
| 468 | config BLK_DEV_CS5536 | ||
| 469 | tristate "CS5536 chipset support" | ||
| 470 | depends on X86_32 | ||
| 471 | select BLK_DEV_IDEDMA_PCI | ||
| 472 | help | ||
| 473 | This option enables support for the AMD CS5536 | ||
| 474 | companion chip used with the Geode LX processor family. | ||
| 475 | |||
| 476 | If unsure, say N. | ||
| 477 | |||
| 468 | config BLK_DEV_HPT366 | 478 | config BLK_DEV_HPT366 |
| 469 | tristate "HPT36X/37X chipset support" | 479 | tristate "HPT36X/37X chipset support" |
| 470 | select BLK_DEV_IDEDMA_PCI | 480 | select BLK_DEV_IDEDMA_PCI |
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index c2b9c93f0095..d0e3d7d5b467 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
| @@ -43,6 +43,7 @@ obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o | |||
| 43 | obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o | 43 | obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o |
| 44 | obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o | 44 | obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o |
| 45 | obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o | 45 | obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o |
| 46 | obj-$(CONFIG_BLK_DEV_CS5536) += cs5536.o | ||
| 46 | obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o | 47 | obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o |
| 47 | obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o | 48 | obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o |
| 48 | obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o | 49 | obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o |
diff --git a/drivers/ide/cs5536.c b/drivers/ide/cs5536.c new file mode 100644 index 000000000000..7a62db719a46 --- /dev/null +++ b/drivers/ide/cs5536.c | |||
| @@ -0,0 +1,308 @@ | |||
| 1 | /* | ||
| 2 | * CS5536 PATA support | ||
| 3 | * (C) 2007 Martin K. Petersen <mkp@mkp.net> | ||
| 4 | * (C) 2009 Bartlomiej Zolnierkiewicz | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | * | ||
| 19 | * Documentation: | ||
| 20 | * Available from AMD web site. | ||
| 21 | * | ||
| 22 | * The IDE timing registers for the CS5536 live in the Geode Machine | ||
| 23 | * Specific Register file and not PCI config space. Most BIOSes | ||
| 24 | * virtualize the PCI registers so the chip looks like a standard IDE | ||
| 25 | * controller. Unfortunately not all implementations get this right. | ||
| 26 | * In particular some have problems with unaligned accesses to the | ||
| 27 | * virtualized PCI registers. This driver always does full dword | ||
| 28 | * writes to work around the issue. Also, in case of a bad BIOS this | ||
| 29 | * driver can be loaded with the "msr=1" parameter which forces using | ||
| 30 | * the Machine Specific Registers to configure the device. | ||
| 31 | */ | ||
| 32 | |||
| 33 | #include <linux/kernel.h> | ||
| 34 | #include <linux/module.h> | ||
| 35 | #include <linux/pci.h> | ||
| 36 | #include <linux/init.h> | ||
| 37 | #include <linux/ide.h> | ||
| 38 | #include <asm/msr.h> | ||
| 39 | |||
| 40 | #define DRV_NAME "cs5536" | ||
| 41 | |||
| 42 | enum { | ||
| 43 | MSR_IDE_CFG = 0x51300010, | ||
| 44 | PCI_IDE_CFG = 0x40, | ||
| 45 | |||
| 46 | CFG = 0, | ||
| 47 | DTC = 2, | ||
| 48 | CAST = 3, | ||
| 49 | ETC = 4, | ||
| 50 | |||
| 51 | IDE_CFG_CHANEN = (1 << 1), | ||
| 52 | IDE_CFG_CABLE = (1 << 17) | (1 << 16), | ||
| 53 | |||
| 54 | IDE_D0_SHIFT = 24, | ||
| 55 | IDE_D1_SHIFT = 16, | ||
| 56 | IDE_DRV_MASK = 0xff, | ||
| 57 | |||
| 58 | IDE_CAST_D0_SHIFT = 6, | ||
| 59 | IDE_CAST_D1_SHIFT = 4, | ||
| 60 | IDE_CAST_DRV_MASK = 0x3, | ||
| 61 | |||
| 62 | IDE_CAST_CMD_SHIFT = 24, | ||
| 63 | IDE_CAST_CMD_MASK = 0xff, | ||
| 64 | |||
| 65 | IDE_ETC_UDMA_MASK = 0xc0, | ||
| 66 | }; | ||
| 67 | |||
| 68 | static int use_msr; | ||
| 69 | |||
| 70 | static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) | ||
| 71 | { | ||
| 72 | if (unlikely(use_msr)) { | ||
| 73 | u32 dummy; | ||
| 74 | |||
| 75 | rdmsr(MSR_IDE_CFG + reg, *val, dummy); | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); | ||
| 80 | } | ||
| 81 | |||
| 82 | static int cs5536_write(struct pci_dev *pdev, int reg, int val) | ||
| 83 | { | ||
| 84 | if (unlikely(use_msr)) { | ||
| 85 | wrmsr(MSR_IDE_CFG + reg, val, 0); | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); | ||
| 90 | } | ||
| 91 | |||
| 92 | static void cs5536_program_dtc(ide_drive_t *drive, u8 tim) | ||
| 93 | { | ||
| 94 | struct pci_dev *pdev = to_pci_dev(drive->hwif->dev); | ||
| 95 | int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT; | ||
| 96 | u32 dtc; | ||
| 97 | |||
| 98 | cs5536_read(pdev, DTC, &dtc); | ||
| 99 | dtc &= ~(IDE_DRV_MASK << dshift); | ||
| 100 | dtc |= tim << dshift; | ||
| 101 | cs5536_write(pdev, DTC, dtc); | ||
| 102 | } | ||
| 103 | |||
| 104 | /** | ||
| 105 | * cs5536_cable_detect - detect cable type | ||
| 106 | * @hwif: Port to detect on | ||
| 107 | * | ||
| 108 | * Perform cable detection for ATA66 capable cable. | ||
| 109 | * | ||
| 110 | * Returns a cable type. | ||
| 111 | */ | ||
| 112 | |||
| 113 | static u8 cs5536_cable_detect(ide_hwif_t *hwif) | ||
| 114 | { | ||
| 115 | struct pci_dev *pdev = to_pci_dev(hwif->dev); | ||
| 116 | u32 cfg; | ||
| 117 | |||
| 118 | cs5536_read(pdev, CFG, &cfg); | ||
| 119 | |||
| 120 | if (cfg & IDE_CFG_CABLE) | ||
| 121 | return ATA_CBL_PATA80; | ||
| 122 | else | ||
| 123 | return ATA_CBL_PATA40; | ||
| 124 | } | ||
| 125 | |||
| 126 | /** | ||
| 127 | * cs5536_set_pio_mode - PIO timing setup | ||
| 128 | * @drive: ATA device | ||
| 129 | * @pio: PIO mode number | ||
| 130 | */ | ||
| 131 | |||
| 132 | static void cs5536_set_pio_mode(ide_drive_t *drive, const u8 pio) | ||
| 133 | { | ||
| 134 | static const u8 drv_timings[5] = { | ||
| 135 | 0x98, 0x55, 0x32, 0x21, 0x20, | ||
| 136 | }; | ||
| 137 | |||
| 138 | static const u8 addr_timings[5] = { | ||
| 139 | 0x2, 0x1, 0x0, 0x0, 0x0, | ||
| 140 | }; | ||
| 141 | |||
| 142 | static const u8 cmd_timings[5] = { | ||
| 143 | 0x99, 0x92, 0x90, 0x22, 0x20, | ||
| 144 | }; | ||
| 145 | |||
| 146 | struct pci_dev *pdev = to_pci_dev(drive->hwif->dev); | ||
| 147 | ide_drive_t *pair = ide_get_pair_dev(drive); | ||
| 148 | int cshift = (drive->dn & 1) ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; | ||
| 149 | u32 cast; | ||
| 150 | u8 cmd_pio = pio; | ||
| 151 | |||
| 152 | if (pair) | ||
| 153 | cmd_pio = min(pio, ide_get_best_pio_mode(pair, 255, 4)); | ||
| 154 | |||
| 155 | drive->drive_data &= (IDE_DRV_MASK << 8); | ||
| 156 | drive->drive_data |= drv_timings[pio]; | ||
| 157 | |||
| 158 | cs5536_program_dtc(drive, drv_timings[pio]); | ||
| 159 | |||
| 160 | cs5536_read(pdev, CAST, &cast); | ||
| 161 | |||
| 162 | cast &= ~(IDE_CAST_DRV_MASK << cshift); | ||
| 163 | cast |= addr_timings[pio] << cshift; | ||
| 164 | |||
| 165 | cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); | ||
| 166 | cast |= cmd_timings[cmd_pio] << IDE_CAST_CMD_SHIFT; | ||
| 167 | |||
| 168 | cs5536_write(pdev, CAST, cast); | ||
| 169 | } | ||
| 170 | |||
| 171 | /** | ||
| 172 | * cs5536_set_dma_mode - DMA timing setup | ||
| 173 | * @drive: ATA device | ||
| 174 | * @mode: DMA mode | ||
| 175 | */ | ||
| 176 | |||
| 177 | static void cs5536_set_dma_mode(ide_drive_t *drive, const u8 mode) | ||
| 178 | { | ||
| 179 | static const u8 udma_timings[6] = { | ||
| 180 | 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, | ||
| 181 | }; | ||
| 182 | |||
| 183 | static const u8 mwdma_timings[3] = { | ||
| 184 | 0x67, 0x21, 0x20, | ||
| 185 | }; | ||
| 186 | |||
| 187 | struct pci_dev *pdev = to_pci_dev(drive->hwif->dev); | ||
| 188 | int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT; | ||
| 189 | u32 etc; | ||
| 190 | |||
| 191 | cs5536_read(pdev, ETC, &etc); | ||
| 192 | |||
| 193 | if (mode >= XFER_UDMA_0) { | ||
| 194 | etc &= ~(IDE_DRV_MASK << dshift); | ||
| 195 | etc |= udma_timings[mode - XFER_UDMA_0] << dshift; | ||
| 196 | } else { /* MWDMA */ | ||
| 197 | etc &= ~(IDE_ETC_UDMA_MASK << dshift); | ||
| 198 | drive->drive_data &= IDE_DRV_MASK; | ||
| 199 | drive->drive_data |= mwdma_timings[mode - XFER_MW_DMA_0] << 8; | ||
| 200 | } | ||
| 201 | |||
| 202 | cs5536_write(pdev, ETC, etc); | ||
| 203 | } | ||
| 204 | |||
| 205 | static void cs5536_dma_start(ide_drive_t *drive) | ||
| 206 | { | ||
| 207 | if (drive->current_speed < XFER_UDMA_0 && | ||
| 208 | (drive->drive_data >> 8) != (drive->drive_data & IDE_DRV_MASK)) | ||
| 209 | cs5536_program_dtc(drive, drive->drive_data >> 8); | ||
| 210 | |||
| 211 | ide_dma_start(drive); | ||
| 212 | } | ||
| 213 | |||
| 214 | static int cs5536_dma_end(ide_drive_t *drive) | ||
| 215 | { | ||
| 216 | int ret = ide_dma_end(drive); | ||
| 217 | |||
| 218 | if (drive->current_speed < XFER_UDMA_0 && | ||
| 219 | (drive->drive_data >> 8) != (drive->drive_data & IDE_DRV_MASK)) | ||
| 220 | cs5536_program_dtc(drive, drive->drive_data & IDE_DRV_MASK); | ||
| 221 | |||
| 222 | return ret; | ||
| 223 | } | ||
| 224 | |||
| 225 | static const struct ide_port_ops cs5536_port_ops = { | ||
| 226 | .set_pio_mode = cs5536_set_pio_mode, | ||
| 227 | .set_dma_mode = cs5536_set_dma_mode, | ||
| 228 | .cable_detect = cs5536_cable_detect, | ||
| 229 | }; | ||
| 230 | |||
| 231 | static const struct ide_dma_ops cs5536_dma_ops = { | ||
| 232 | .dma_host_set = ide_dma_host_set, | ||
| 233 | .dma_setup = ide_dma_setup, | ||
| 234 | .dma_exec_cmd = ide_dma_exec_cmd, | ||
| 235 | .dma_start = cs5536_dma_start, | ||
| 236 | .dma_end = cs5536_dma_end, | ||
| 237 | .dma_test_irq = ide_dma_test_irq, | ||
| 238 | .dma_lost_irq = ide_dma_lost_irq, | ||
| 239 | .dma_timeout = ide_dma_timeout, | ||
| 240 | }; | ||
| 241 | |||
| 242 | static const struct ide_port_info cs5536_info = { | ||
| 243 | .name = DRV_NAME, | ||
| 244 | .port_ops = &cs5536_port_ops, | ||
| 245 | .dma_ops = &cs5536_dma_ops, | ||
| 246 | .host_flags = IDE_HFLAG_SINGLE, | ||
| 247 | .pio_mask = ATA_PIO4, | ||
| 248 | .mwdma_mask = ATA_MWDMA2, | ||
| 249 | .udma_mask = ATA_UDMA5, | ||
| 250 | }; | ||
| 251 | |||
| 252 | /** | ||
| 253 | * cs5536_init_one | ||
| 254 | * @dev: PCI device | ||
| 255 | * @id: Entry in match table | ||
| 256 | */ | ||
| 257 | |||
| 258 | static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) | ||
| 259 | { | ||
| 260 | u32 cfg; | ||
| 261 | |||
| 262 | if (use_msr) | ||
| 263 | printk(KERN_INFO DRV_NAME ": Using MSR regs instead of PCI\n"); | ||
| 264 | |||
| 265 | cs5536_read(dev, CFG, &cfg); | ||
| 266 | |||
| 267 | if ((cfg & IDE_CFG_CHANEN) == 0) { | ||
| 268 | printk(KERN_ERR DRV_NAME ": disabled by BIOS\n"); | ||
| 269 | return -ENODEV; | ||
| 270 | } | ||
| 271 | |||
| 272 | return ide_pci_init_one(dev, &cs5536_info, NULL); | ||
| 273 | } | ||
| 274 | |||
| 275 | static const struct pci_device_id cs5536_pci_tbl[] = { | ||
| 276 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), }, | ||
| 277 | { }, | ||
| 278 | }; | ||
| 279 | |||
| 280 | static struct pci_driver cs5536_pci_driver = { | ||
| 281 | .name = DRV_NAME, | ||
| 282 | .id_table = cs5536_pci_tbl, | ||
| 283 | .probe = cs5536_init_one, | ||
| 284 | .remove = ide_pci_remove, | ||
| 285 | .suspend = ide_pci_suspend, | ||
| 286 | .resume = ide_pci_resume, | ||
| 287 | }; | ||
| 288 | |||
| 289 | static int __init cs5536_init(void) | ||
| 290 | { | ||
| 291 | return pci_register_driver(&cs5536_pci_driver); | ||
| 292 | } | ||
| 293 | |||
| 294 | static void __exit cs5536_exit(void) | ||
| 295 | { | ||
| 296 | pci_unregister_driver(&cs5536_pci_driver); | ||
| 297 | } | ||
| 298 | |||
| 299 | MODULE_AUTHOR("Martin K. Petersen, Bartlomiej Zolnierkiewicz"); | ||
| 300 | MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller"); | ||
| 301 | MODULE_LICENSE("GPL"); | ||
| 302 | MODULE_DEVICE_TABLE(pci, cs5536_pci_tbl); | ||
| 303 | |||
| 304 | module_param_named(msr, use_msr, int, 0644); | ||
| 305 | MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); | ||
| 306 | |||
| 307 | module_init(cs5536_init); | ||
| 308 | module_exit(cs5536_exit); | ||
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 97a35c667aee..415d7e24f2b6 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c | |||
| @@ -534,7 +534,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) | |||
| 534 | d.dma_ops = NULL; | 534 | d.dma_ops = NULL; |
| 535 | } | 535 | } |
| 536 | 536 | ||
| 537 | ret = ide_host_register(host, NULL, hws); | 537 | ret = ide_host_register(host, &d, hws); |
| 538 | if (ret) | 538 | if (ret) |
| 539 | goto err_free; | 539 | goto err_free; |
| 540 | 540 | ||
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index d8f295bdad76..ec7d07fa570a 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c | |||
| @@ -282,7 +282,7 @@ static int do_drive_get_GTF(ide_drive_t *drive, | |||
| 282 | port = hwif->channel ? drive->dn - 2: drive->dn; | 282 | port = hwif->channel ? drive->dn - 2: drive->dn; |
| 283 | 283 | ||
| 284 | DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", | 284 | DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", |
| 285 | hwif->name, dev->bus_id, port, hwif->channel); | 285 | hwif->name, dev_name(dev), port, hwif->channel); |
| 286 | 286 | ||
| 287 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) { | 287 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) { |
| 288 | DEBPRINT("%s drive %d:%d not present\n", | 288 | DEBPRINT("%s drive %d:%d not present\n", |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index cae69372cf45..0bfeb0c79d6e 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
| @@ -787,6 +787,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
| 787 | if (blk_fs_request(rq)) { | 787 | if (blk_fs_request(rq)) { |
| 788 | ide_end_request(drive, 1, rq->nr_sectors); | 788 | ide_end_request(drive, 1, rq->nr_sectors); |
| 789 | return ide_stopped; | 789 | return ide_stopped; |
| 790 | } else if (rq->cmd_type == REQ_TYPE_ATA_PC && !rq->bio) { | ||
| 791 | ide_end_request(drive, 1, 1); | ||
| 792 | return ide_stopped; | ||
| 790 | } | 793 | } |
| 791 | goto end_request; | 794 | goto end_request; |
| 792 | } | 795 | } |
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index cc163319dfbd..9ee51adf567f 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
| @@ -418,11 +418,14 @@ void ide_map_sg(ide_drive_t *drive, struct request *rq) | |||
| 418 | ide_hwif_t *hwif = drive->hwif; | 418 | ide_hwif_t *hwif = drive->hwif; |
| 419 | struct scatterlist *sg = hwif->sg_table; | 419 | struct scatterlist *sg = hwif->sg_table; |
| 420 | 420 | ||
| 421 | if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) { | 421 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { |
| 422 | hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); | ||
| 423 | } else { | ||
| 424 | sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); | 422 | sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); |
| 425 | hwif->sg_nents = 1; | 423 | hwif->sg_nents = 1; |
| 424 | } else if (!rq->bio) { | ||
| 425 | sg_init_one(sg, rq->data, rq->data_len); | ||
| 426 | hwif->sg_nents = 1; | ||
| 427 | } else { | ||
| 428 | hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); | ||
| 426 | } | 429 | } |
| 427 | } | 430 | } |
| 428 | 431 | ||
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 0db1ed9f5fc2..ce0818a993f6 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
| @@ -1467,6 +1467,30 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) | |||
| 1467 | } | 1467 | } |
| 1468 | EXPORT_SYMBOL_GPL(ide_host_alloc); | 1468 | EXPORT_SYMBOL_GPL(ide_host_alloc); |
| 1469 | 1469 | ||
| 1470 | static void ide_port_free(ide_hwif_t *hwif) | ||
| 1471 | { | ||
| 1472 | ide_port_free_devices(hwif); | ||
| 1473 | ide_free_port_slot(hwif->index); | ||
| 1474 | kfree(hwif); | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | static void ide_disable_port(ide_hwif_t *hwif) | ||
| 1478 | { | ||
| 1479 | struct ide_host *host = hwif->host; | ||
| 1480 | int i; | ||
| 1481 | |||
| 1482 | printk(KERN_INFO "%s: disabling port\n", hwif->name); | ||
| 1483 | |||
| 1484 | for (i = 0; i < MAX_HOST_PORTS; i++) { | ||
| 1485 | if (host->ports[i] == hwif) { | ||
| 1486 | host->ports[i] = NULL; | ||
| 1487 | host->n_ports--; | ||
| 1488 | } | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | ide_port_free(hwif); | ||
| 1492 | } | ||
| 1493 | |||
| 1470 | int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | 1494 | int ide_host_register(struct ide_host *host, const struct ide_port_info *d, |
| 1471 | hw_regs_t **hws) | 1495 | hw_regs_t **hws) |
| 1472 | { | 1496 | { |
| @@ -1507,8 +1531,12 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | |||
| 1507 | hwif->present = 1; | 1531 | hwif->present = 1; |
| 1508 | 1532 | ||
| 1509 | if (hwif->chipset != ide_4drives || !hwif->mate || | 1533 | if (hwif->chipset != ide_4drives || !hwif->mate || |
| 1510 | !hwif->mate->present) | 1534 | !hwif->mate->present) { |
| 1511 | ide_register_port(hwif); | 1535 | if (ide_register_port(hwif)) { |
| 1536 | ide_disable_port(hwif); | ||
| 1537 | continue; | ||
| 1538 | } | ||
| 1539 | } | ||
| 1512 | 1540 | ||
| 1513 | if (hwif->present) | 1541 | if (hwif->present) |
| 1514 | ide_port_tune_devices(hwif); | 1542 | ide_port_tune_devices(hwif); |
| @@ -1521,7 +1549,8 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | |||
| 1521 | if (hwif_init(hwif) == 0) { | 1549 | if (hwif_init(hwif) == 0) { |
| 1522 | printk(KERN_INFO "%s: failed to initialize IDE " | 1550 | printk(KERN_INFO "%s: failed to initialize IDE " |
| 1523 | "interface\n", hwif->name); | 1551 | "interface\n", hwif->name); |
| 1524 | hwif->present = 0; | 1552 | device_unregister(&hwif->gendev); |
| 1553 | ide_disable_port(hwif); | ||
| 1525 | continue; | 1554 | continue; |
| 1526 | } | 1555 | } |
| 1527 | 1556 | ||
| @@ -1660,12 +1689,8 @@ void ide_host_free(struct ide_host *host) | |||
| 1660 | int i; | 1689 | int i; |
| 1661 | 1690 | ||
| 1662 | ide_host_for_each_port(i, hwif, host) { | 1691 | ide_host_for_each_port(i, hwif, host) { |
| 1663 | if (hwif == NULL) | 1692 | if (hwif) |
| 1664 | continue; | 1693 | ide_port_free(hwif); |
| 1665 | |||
| 1666 | ide_port_free_devices(hwif); | ||
| 1667 | ide_free_port_slot(hwif->index); | ||
| 1668 | kfree(hwif); | ||
| 1669 | } | 1694 | } |
| 1670 | 1695 | ||
| 1671 | kfree(host); | 1696 | kfree(host); |
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index 882f6f07c476..40b0812a045c 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c | |||
| @@ -261,9 +261,9 @@ static int tx4939ide_build_dmatable(ide_drive_t *drive, struct request *rq) | |||
| 261 | bcount = cur_len; | 261 | bcount = cur_len; |
| 262 | /* | 262 | /* |
| 263 | * This workaround for zero count seems required. | 263 | * This workaround for zero count seems required. |
| 264 | * (standard ide_build_dmatable do it too) | 264 | * (standard ide_build_dmatable does it too) |
| 265 | */ | 265 | */ |
| 266 | if ((bcount & 0xffff) == 0x0000) | 266 | if (bcount == 0x10000) |
| 267 | bcount = 0x8000; | 267 | bcount = 0x8000; |
| 268 | *table++ = bcount & 0xffff; | 268 | *table++ = bcount & 0xffff; |
| 269 | *table++ = cur_addr; | 269 | *table++ = cur_addr; |
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index 703c3eeb20a8..6092fe3f409d 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c | |||
| @@ -448,6 +448,11 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i | |||
| 448 | d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; | 448 | d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; |
| 449 | #endif | 449 | #endif |
| 450 | 450 | ||
| 451 | #ifdef CONFIG_AMIGAONE | ||
| 452 | if (machine_is(amigaone)) | ||
| 453 | d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; | ||
| 454 | #endif | ||
| 455 | |||
| 451 | d.udma_mask = via_config->udma_mask; | 456 | d.udma_mask = via_config->udma_mask; |
| 452 | 457 | ||
| 453 | vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); | 458 | vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); |
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index 577c0d29849d..2291c5f5af51 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
| @@ -170,12 +170,17 @@ void asl_stop(struct whc *whc) | |||
| 170 | void asl_update(struct whc *whc, uint32_t wusbcmd) | 170 | void asl_update(struct whc *whc, uint32_t wusbcmd) |
| 171 | { | 171 | { |
| 172 | struct wusbhc *wusbhc = &whc->wusbhc; | 172 | struct wusbhc *wusbhc = &whc->wusbhc; |
| 173 | long t; | ||
| 173 | 174 | ||
| 174 | mutex_lock(&wusbhc->mutex); | 175 | mutex_lock(&wusbhc->mutex); |
| 175 | if (wusbhc->active) { | 176 | if (wusbhc->active) { |
| 176 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 177 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); |
| 177 | wait_event(whc->async_list_wq, | 178 | t = wait_event_timeout( |
| 178 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0); | 179 | whc->async_list_wq, |
| 180 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0, | ||
| 181 | msecs_to_jiffies(1000)); | ||
| 182 | if (t == 0) | ||
| 183 | whc_hw_error(whc, "ASL update timeout"); | ||
| 179 | } | 184 | } |
| 180 | mutex_unlock(&wusbhc->mutex); | 185 | mutex_unlock(&wusbhc->mutex); |
| 181 | } | 186 | } |
diff --git a/drivers/usb/host/whci/hw.c b/drivers/usb/host/whci/hw.c index d498e7203217..6afa2e379160 100644 --- a/drivers/usb/host/whci/hw.c +++ b/drivers/usb/host/whci/hw.c | |||
| @@ -87,3 +87,18 @@ out: | |||
| 87 | 87 | ||
| 88 | return ret; | 88 | return ret; |
| 89 | } | 89 | } |
| 90 | |||
| 91 | /** | ||
| 92 | * whc_hw_error - recover from a hardware error | ||
| 93 | * @whc: the WHCI HC that broke. | ||
| 94 | * @reason: a description of the failure. | ||
| 95 | * | ||
| 96 | * Recover from broken hardware with a full reset. | ||
| 97 | */ | ||
| 98 | void whc_hw_error(struct whc *whc, const char *reason) | ||
| 99 | { | ||
| 100 | struct wusbhc *wusbhc = &whc->wusbhc; | ||
| 101 | |||
| 102 | dev_err(&whc->umc->dev, "hardware error: %s\n", reason); | ||
| 103 | wusbhc_reset_all(wusbhc); | ||
| 104 | } | ||
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index 2ae5abf69a6a..7dc85a0bee7c 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c | |||
| @@ -183,12 +183,17 @@ void pzl_stop(struct whc *whc) | |||
| 183 | void pzl_update(struct whc *whc, uint32_t wusbcmd) | 183 | void pzl_update(struct whc *whc, uint32_t wusbcmd) |
| 184 | { | 184 | { |
| 185 | struct wusbhc *wusbhc = &whc->wusbhc; | 185 | struct wusbhc *wusbhc = &whc->wusbhc; |
| 186 | long t; | ||
| 186 | 187 | ||
| 187 | mutex_lock(&wusbhc->mutex); | 188 | mutex_lock(&wusbhc->mutex); |
| 188 | if (wusbhc->active) { | 189 | if (wusbhc->active) { |
| 189 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 190 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); |
| 190 | wait_event(whc->periodic_list_wq, | 191 | t = wait_event_timeout( |
| 191 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0); | 192 | whc->periodic_list_wq, |
| 193 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0, | ||
| 194 | msecs_to_jiffies(1000)); | ||
| 195 | if (t == 0) | ||
| 196 | whc_hw_error(whc, "PZL update timeout"); | ||
| 192 | } | 197 | } |
| 193 | mutex_unlock(&wusbhc->mutex); | 198 | mutex_unlock(&wusbhc->mutex); |
| 194 | } | 199 | } |
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index 0f3540f04f53..d3543a181dc9 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h | |||
| @@ -137,6 +137,7 @@ void whc_clean_up(struct whc *whc); | |||
| 137 | /* hw.c */ | 137 | /* hw.c */ |
| 138 | void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); | 138 | void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); |
| 139 | int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); | 139 | int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); |
| 140 | void whc_hw_error(struct whc *whc, const char *reason); | ||
| 140 | 141 | ||
| 141 | /* wusb.c */ | 142 | /* wusb.c */ |
| 142 | int whc_wusbhc_start(struct wusbhc *wusbhc); | 143 | int whc_wusbhc_start(struct wusbhc *wusbhc); |
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index e2e7e4bc8463..8e18141bb2e0 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c | |||
| @@ -386,6 +386,7 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, | |||
| 386 | | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); | 386 | | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); |
| 387 | port->change |= USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE; | 387 | port->change |= USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE; |
| 388 | if (wusb_dev) { | 388 | if (wusb_dev) { |
| 389 | dev_dbg(wusbhc->dev, "disconnecting device from port %d\n", wusb_dev->port_idx); | ||
| 389 | if (!list_empty(&wusb_dev->cack_node)) | 390 | if (!list_empty(&wusb_dev->cack_node)) |
| 390 | list_del_init(&wusb_dev->cack_node); | 391 | list_del_init(&wusb_dev->cack_node); |
| 391 | /* For the one in cack_add() */ | 392 | /* For the one in cack_add() */ |
diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index 3937bf6f8cef..9fe4246cecb9 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c | |||
| @@ -100,6 +100,9 @@ static int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx) | |||
| 100 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); | 100 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); |
| 101 | struct wusb_dev *wusb_dev = port->wusb_dev; | 101 | struct wusb_dev *wusb_dev = port->wusb_dev; |
| 102 | 102 | ||
| 103 | if (wusb_dev == NULL) | ||
| 104 | return -ENOTCONN; | ||
| 105 | |||
| 103 | port->status |= USB_PORT_STAT_RESET; | 106 | port->status |= USB_PORT_STAT_RESET; |
| 104 | port->change |= USB_PORT_STAT_C_RESET; | 107 | port->change |= USB_PORT_STAT_C_RESET; |
| 105 | 108 | ||
diff --git a/drivers/uwb/allocator.c b/drivers/uwb/allocator.c index c8185e6b0cd5..c13cec7dcbc5 100644 --- a/drivers/uwb/allocator.c +++ b/drivers/uwb/allocator.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | */ | 17 | */ |
| 18 | #include <linux/version.h> | ||
| 19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 20 | #include <linux/uwb.h> | 19 | #include <linux/uwb.h> |
| 21 | 20 | ||
diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index 2b4f9406789d..4f5ca99a04b9 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c | |||
| @@ -66,14 +66,14 @@ static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg, | |||
| 66 | } else | 66 | } else |
| 67 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n"); | 67 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n"); |
| 68 | 68 | ||
| 69 | spin_lock(&rc->rsvs_lock); | 69 | spin_lock_bh(&rc->rsvs_lock); |
| 70 | if (rc->set_drp_ie_pending > 1) { | 70 | if (rc->set_drp_ie_pending > 1) { |
| 71 | rc->set_drp_ie_pending = 0; | 71 | rc->set_drp_ie_pending = 0; |
| 72 | uwb_rsv_queue_update(rc); | 72 | uwb_rsv_queue_update(rc); |
| 73 | } else { | 73 | } else { |
| 74 | rc->set_drp_ie_pending = 0; | 74 | rc->set_drp_ie_pending = 0; |
| 75 | } | 75 | } |
| 76 | spin_unlock(&rc->rsvs_lock); | 76 | spin_unlock_bh(&rc->rsvs_lock); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | /** | 79 | /** |
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c index ec6eecb32f30..6b76f4bb4cc7 100644 --- a/drivers/uwb/rsv.c +++ b/drivers/uwb/rsv.c | |||
| @@ -114,7 +114,8 @@ void uwb_rsv_dump(char *text, struct uwb_rsv *rsv) | |||
| 114 | devaddr = rsv->target.devaddr; | 114 | devaddr = rsv->target.devaddr; |
| 115 | uwb_dev_addr_print(target, sizeof(target), &devaddr); | 115 | uwb_dev_addr_print(target, sizeof(target), &devaddr); |
| 116 | 116 | ||
| 117 | dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state)); | 117 | dev_dbg(dev, "rsv %s %s -> %s: %s\n", |
| 118 | text, owner, target, uwb_rsv_state_str(rsv->state)); | ||
| 118 | } | 119 | } |
| 119 | 120 | ||
| 120 | static void uwb_rsv_release(struct kref *kref) | 121 | static void uwb_rsv_release(struct kref *kref) |
| @@ -511,8 +512,7 @@ void uwb_rsv_remove(struct uwb_rsv *rsv) | |||
| 511 | 512 | ||
| 512 | if (uwb_rsv_is_owner(rsv)) | 513 | if (uwb_rsv_is_owner(rsv)) |
| 513 | uwb_rsv_put_stream(rsv); | 514 | uwb_rsv_put_stream(rsv); |
| 514 | 515 | ||
| 515 | del_timer_sync(&rsv->timer); | ||
| 516 | uwb_dev_put(rsv->owner); | 516 | uwb_dev_put(rsv->owner); |
| 517 | if (rsv->target.type == UWB_RSV_TARGET_DEV) | 517 | if (rsv->target.type == UWB_RSV_TARGET_DEV) |
| 518 | uwb_dev_put(rsv->target.dev); | 518 | uwb_dev_put(rsv->target.dev); |
| @@ -870,7 +870,7 @@ void uwb_rsv_queue_update(struct uwb_rc *rc) | |||
| 870 | */ | 870 | */ |
| 871 | void uwb_rsv_sched_update(struct uwb_rc *rc) | 871 | void uwb_rsv_sched_update(struct uwb_rc *rc) |
| 872 | { | 872 | { |
| 873 | spin_lock(&rc->rsvs_lock); | 873 | spin_lock_bh(&rc->rsvs_lock); |
| 874 | if (!delayed_work_pending(&rc->rsv_update_work)) { | 874 | if (!delayed_work_pending(&rc->rsv_update_work)) { |
| 875 | if (rc->set_drp_ie_pending > 0) { | 875 | if (rc->set_drp_ie_pending > 0) { |
| 876 | rc->set_drp_ie_pending++; | 876 | rc->set_drp_ie_pending++; |
| @@ -879,7 +879,7 @@ void uwb_rsv_sched_update(struct uwb_rc *rc) | |||
| 879 | uwb_rsv_queue_update(rc); | 879 | uwb_rsv_queue_update(rc); |
| 880 | } | 880 | } |
| 881 | unlock: | 881 | unlock: |
| 882 | spin_unlock(&rc->rsvs_lock); | 882 | spin_unlock_bh(&rc->rsvs_lock); |
| 883 | } | 883 | } |
| 884 | 884 | ||
| 885 | /* | 885 | /* |
| @@ -943,13 +943,22 @@ void uwb_rsv_remove_all(struct uwb_rc *rc) | |||
| 943 | 943 | ||
| 944 | mutex_lock(&rc->rsvs_mutex); | 944 | mutex_lock(&rc->rsvs_mutex); |
| 945 | list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { | 945 | list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { |
| 946 | uwb_rsv_remove(rsv); | 946 | if (rsv->state != UWB_RSV_STATE_NONE) |
| 947 | uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); | ||
| 948 | del_timer_sync(&rsv->timer); | ||
| 947 | } | 949 | } |
| 948 | /* Cancel any postponed update. */ | 950 | /* Cancel any postponed update. */ |
| 949 | rc->set_drp_ie_pending = 0; | 951 | rc->set_drp_ie_pending = 0; |
| 950 | mutex_unlock(&rc->rsvs_mutex); | 952 | mutex_unlock(&rc->rsvs_mutex); |
| 951 | 953 | ||
| 952 | cancel_delayed_work_sync(&rc->rsv_update_work); | 954 | cancel_delayed_work_sync(&rc->rsv_update_work); |
| 955 | flush_workqueue(rc->rsv_workq); | ||
| 956 | |||
| 957 | mutex_lock(&rc->rsvs_mutex); | ||
| 958 | list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { | ||
| 959 | uwb_rsv_remove(rsv); | ||
| 960 | } | ||
| 961 | mutex_unlock(&rc->rsvs_mutex); | ||
| 953 | } | 962 | } |
| 954 | 963 | ||
| 955 | void uwb_rsv_init(struct uwb_rc *rc) | 964 | void uwb_rsv_init(struct uwb_rc *rc) |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index bef6b45e8a5c..330aacbdec1f 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -192,7 +192,7 @@ static irqreturn_t vp_interrupt(int irq, void *opaque) | |||
| 192 | drv = container_of(vp_dev->vdev.dev.driver, | 192 | drv = container_of(vp_dev->vdev.dev.driver, |
| 193 | struct virtio_driver, driver); | 193 | struct virtio_driver, driver); |
| 194 | 194 | ||
| 195 | if (drv->config_changed) | 195 | if (drv && drv->config_changed) |
| 196 | drv->config_changed(&vp_dev->vdev); | 196 | drv->config_changed(&vp_dev->vdev); |
| 197 | } | 197 | } |
| 198 | 198 | ||
diff --git a/include/linux/bio.h b/include/linux/bio.h index 0942765cf8c0..2aa283ab062b 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
| @@ -451,12 +451,13 @@ extern struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly; | |||
| 451 | 451 | ||
| 452 | #ifdef CONFIG_HIGHMEM | 452 | #ifdef CONFIG_HIGHMEM |
| 453 | /* | 453 | /* |
| 454 | * remember to add offset! and never ever reenable interrupts between a | 454 | * remember never ever reenable interrupts between a bvec_kmap_irq and |
| 455 | * bvec_kmap_irq and bvec_kunmap_irq!! | 455 | * bvec_kunmap_irq! |
| 456 | * | 456 | * |
| 457 | * This function MUST be inlined - it plays with the CPU interrupt flags. | 457 | * This function MUST be inlined - it plays with the CPU interrupt flags. |
| 458 | */ | 458 | */ |
| 459 | static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags) | 459 | static __always_inline char *bvec_kmap_irq(struct bio_vec *bvec, |
| 460 | unsigned long *flags) | ||
| 460 | { | 461 | { |
| 461 | unsigned long addr; | 462 | unsigned long addr; |
| 462 | 463 | ||
| @@ -472,7 +473,8 @@ static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags) | |||
| 472 | return (char *) addr + bvec->bv_offset; | 473 | return (char *) addr + bvec->bv_offset; |
| 473 | } | 474 | } |
| 474 | 475 | ||
| 475 | static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags) | 476 | static __always_inline void bvec_kunmap_irq(char *buffer, |
| 477 | unsigned long *flags) | ||
| 476 | { | 478 | { |
| 477 | unsigned long ptr = (unsigned long) buffer & PAGE_MASK; | 479 | unsigned long ptr = (unsigned long) buffer & PAGE_MASK; |
| 478 | 480 | ||
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d08c4b8219a6..dcaa0fd84b02 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -455,7 +455,7 @@ struct request_queue | |||
| 455 | 455 | ||
| 456 | #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ | 456 | #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ |
| 457 | (1 << QUEUE_FLAG_CLUSTER) | \ | 457 | (1 << QUEUE_FLAG_CLUSTER) | \ |
| 458 | 1 << QUEUE_FLAG_STACKABLE) | 458 | (1 << QUEUE_FLAG_STACKABLE)) |
| 459 | 459 | ||
| 460 | static inline int queue_is_locked(struct request_queue *q) | 460 | static inline int queue_is_locked(struct request_queue *q) |
| 461 | { | 461 | { |
diff --git a/include/linux/module.h b/include/linux/module.h index 4f7ea12463d3..f3b8329eb5b8 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
| @@ -219,11 +219,6 @@ void *__symbol_get_gpl(const char *symbol); | |||
| 219 | 219 | ||
| 220 | #endif | 220 | #endif |
| 221 | 221 | ||
| 222 | struct module_ref | ||
| 223 | { | ||
| 224 | local_t count; | ||
| 225 | } ____cacheline_aligned; | ||
| 226 | |||
| 227 | enum module_state | 222 | enum module_state |
| 228 | { | 223 | { |
| 229 | MODULE_STATE_LIVE, | 224 | MODULE_STATE_LIVE, |
| @@ -344,8 +339,11 @@ struct module | |||
| 344 | /* Destruction function. */ | 339 | /* Destruction function. */ |
| 345 | void (*exit)(void); | 340 | void (*exit)(void); |
| 346 | 341 | ||
| 347 | /* Reference counts */ | 342 | #ifdef CONFIG_SMP |
| 348 | struct module_ref ref[NR_CPUS]; | 343 | char *refptr; |
| 344 | #else | ||
| 345 | local_t ref; | ||
| 346 | #endif | ||
| 349 | #endif | 347 | #endif |
| 350 | }; | 348 | }; |
| 351 | #ifndef MODULE_ARCH_INIT | 349 | #ifndef MODULE_ARCH_INIT |
| @@ -395,13 +393,22 @@ void __symbol_put(const char *symbol); | |||
| 395 | #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x) | 393 | #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x) |
| 396 | void symbol_put_addr(void *addr); | 394 | void symbol_put_addr(void *addr); |
| 397 | 395 | ||
| 396 | static inline local_t *__module_ref_addr(struct module *mod, int cpu) | ||
| 397 | { | ||
| 398 | #ifdef CONFIG_SMP | ||
| 399 | return (local_t *) (mod->refptr + per_cpu_offset(cpu)); | ||
| 400 | #else | ||
| 401 | return &mod->ref; | ||
| 402 | #endif | ||
| 403 | } | ||
| 404 | |||
| 398 | /* Sometimes we know we already have a refcount, and it's easier not | 405 | /* Sometimes we know we already have a refcount, and it's easier not |
| 399 | to handle the error case (which only happens with rmmod --wait). */ | 406 | to handle the error case (which only happens with rmmod --wait). */ |
| 400 | static inline void __module_get(struct module *module) | 407 | static inline void __module_get(struct module *module) |
| 401 | { | 408 | { |
| 402 | if (module) { | 409 | if (module) { |
| 403 | BUG_ON(module_refcount(module) == 0); | 410 | BUG_ON(module_refcount(module) == 0); |
| 404 | local_inc(&module->ref[get_cpu()].count); | 411 | local_inc(__module_ref_addr(module, get_cpu())); |
| 405 | put_cpu(); | 412 | put_cpu(); |
| 406 | } | 413 | } |
| 407 | } | 414 | } |
| @@ -413,7 +420,7 @@ static inline int try_module_get(struct module *module) | |||
| 413 | if (module) { | 420 | if (module) { |
| 414 | unsigned int cpu = get_cpu(); | 421 | unsigned int cpu = get_cpu(); |
| 415 | if (likely(module_is_live(module))) | 422 | if (likely(module_is_live(module))) |
| 416 | local_inc(&module->ref[cpu].count); | 423 | local_inc(__module_ref_addr(module, cpu)); |
| 417 | else | 424 | else |
| 418 | ret = 0; | 425 | ret = 0; |
| 419 | put_cpu(); | 426 | put_cpu(); |
diff --git a/kernel/module.c b/kernel/module.c index e8b51d41dd72..ba22484a987e 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -573,13 +573,13 @@ static char last_unloaded_module[MODULE_NAME_LEN+1]; | |||
| 573 | /* Init the unload section of the module. */ | 573 | /* Init the unload section of the module. */ |
| 574 | static void module_unload_init(struct module *mod) | 574 | static void module_unload_init(struct module *mod) |
| 575 | { | 575 | { |
| 576 | unsigned int i; | 576 | int cpu; |
| 577 | 577 | ||
| 578 | INIT_LIST_HEAD(&mod->modules_which_use_me); | 578 | INIT_LIST_HEAD(&mod->modules_which_use_me); |
| 579 | for (i = 0; i < NR_CPUS; i++) | 579 | for_each_possible_cpu(cpu) |
| 580 | local_set(&mod->ref[i].count, 0); | 580 | local_set(__module_ref_addr(mod, cpu), 0); |
| 581 | /* Hold reference count during initialization. */ | 581 | /* Hold reference count during initialization. */ |
| 582 | local_set(&mod->ref[raw_smp_processor_id()].count, 1); | 582 | local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1); |
| 583 | /* Backwards compatibility macros put refcount during init. */ | 583 | /* Backwards compatibility macros put refcount during init. */ |
| 584 | mod->waiter = current; | 584 | mod->waiter = current; |
| 585 | } | 585 | } |
| @@ -717,10 +717,11 @@ static int try_stop_module(struct module *mod, int flags, int *forced) | |||
| 717 | 717 | ||
| 718 | unsigned int module_refcount(struct module *mod) | 718 | unsigned int module_refcount(struct module *mod) |
| 719 | { | 719 | { |
| 720 | unsigned int i, total = 0; | 720 | unsigned int total = 0; |
| 721 | int cpu; | ||
| 721 | 722 | ||
| 722 | for (i = 0; i < NR_CPUS; i++) | 723 | for_each_possible_cpu(cpu) |
| 723 | total += local_read(&mod->ref[i].count); | 724 | total += local_read(__module_ref_addr(mod, cpu)); |
| 724 | return total; | 725 | return total; |
| 725 | } | 726 | } |
| 726 | EXPORT_SYMBOL(module_refcount); | 727 | EXPORT_SYMBOL(module_refcount); |
| @@ -894,7 +895,7 @@ void module_put(struct module *module) | |||
| 894 | { | 895 | { |
| 895 | if (module) { | 896 | if (module) { |
| 896 | unsigned int cpu = get_cpu(); | 897 | unsigned int cpu = get_cpu(); |
| 897 | local_dec(&module->ref[cpu].count); | 898 | local_dec(__module_ref_addr(module, cpu)); |
| 898 | /* Maybe they're waiting for us to drop reference? */ | 899 | /* Maybe they're waiting for us to drop reference? */ |
| 899 | if (unlikely(!module_is_live(module))) | 900 | if (unlikely(!module_is_live(module))) |
| 900 | wake_up_process(module->waiter); | 901 | wake_up_process(module->waiter); |
| @@ -1464,7 +1465,10 @@ static void free_module(struct module *mod) | |||
| 1464 | kfree(mod->args); | 1465 | kfree(mod->args); |
| 1465 | if (mod->percpu) | 1466 | if (mod->percpu) |
| 1466 | percpu_modfree(mod->percpu); | 1467 | percpu_modfree(mod->percpu); |
| 1467 | 1468 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | |
| 1469 | if (mod->refptr) | ||
| 1470 | percpu_modfree(mod->refptr); | ||
| 1471 | #endif | ||
| 1468 | /* Free lock-classes: */ | 1472 | /* Free lock-classes: */ |
| 1469 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1473 | lockdep_free_key_range(mod->module_core, mod->core_size); |
| 1470 | 1474 | ||
| @@ -2011,6 +2015,14 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2011 | if (err < 0) | 2015 | if (err < 0) |
| 2012 | goto free_mod; | 2016 | goto free_mod; |
| 2013 | 2017 | ||
| 2018 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
| 2019 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | ||
| 2020 | mod->name); | ||
| 2021 | if (!mod->refptr) { | ||
| 2022 | err = -ENOMEM; | ||
| 2023 | goto free_mod; | ||
| 2024 | } | ||
| 2025 | #endif | ||
| 2014 | if (pcpuindex) { | 2026 | if (pcpuindex) { |
| 2015 | /* We have a special allocation for this section. */ | 2027 | /* We have a special allocation for this section. */ |
| 2016 | percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, | 2028 | percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, |
| @@ -2018,7 +2030,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2018 | mod->name); | 2030 | mod->name); |
| 2019 | if (!percpu) { | 2031 | if (!percpu) { |
| 2020 | err = -ENOMEM; | 2032 | err = -ENOMEM; |
| 2021 | goto free_mod; | 2033 | goto free_percpu; |
| 2022 | } | 2034 | } |
| 2023 | sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2035 | sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2024 | mod->percpu = percpu; | 2036 | mod->percpu = percpu; |
| @@ -2282,6 +2294,9 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2282 | free_percpu: | 2294 | free_percpu: |
| 2283 | if (percpu) | 2295 | if (percpu) |
| 2284 | percpu_modfree(percpu); | 2296 | percpu_modfree(percpu); |
| 2297 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
| 2298 | percpu_modfree(mod->refptr); | ||
| 2299 | #endif | ||
| 2285 | free_mod: | 2300 | free_mod: |
| 2286 | kfree(args); | 2301 | kfree(args); |
| 2287 | free_hdr: | 2302 | free_hdr: |
