diff options
Diffstat (limited to 'drivers/scsi')
| -rw-r--r-- | drivers/scsi/BusLogic.c | 16 | ||||
| -rw-r--r-- | drivers/scsi/aacraid/linit.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 9 | ||||
| -rw-r--r-- | drivers/scsi/sd.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/sg.c | 176 |
6 files changed, 116 insertions, 91 deletions
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index feab3a5e50b5..757eb0716d45 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c | |||
| @@ -696,7 +696,7 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) | |||
| 696 | while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, | 696 | while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, |
| 697 | PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, | 697 | PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, |
| 698 | pci_device)) != NULL) { | 698 | pci_device)) != NULL) { |
| 699 | struct blogic_adapter *adapter = adapter; | 699 | struct blogic_adapter *host_adapter = adapter; |
| 700 | struct blogic_adapter_info adapter_info; | 700 | struct blogic_adapter_info adapter_info; |
| 701 | enum blogic_isa_ioport mod_ioaddr_req; | 701 | enum blogic_isa_ioport mod_ioaddr_req; |
| 702 | unsigned char bus; | 702 | unsigned char bus; |
| @@ -744,9 +744,9 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) | |||
| 744 | known and enabled, note that the particular Standard ISA I/O | 744 | known and enabled, note that the particular Standard ISA I/O |
| 745 | Address should not be probed. | 745 | Address should not be probed. |
| 746 | */ | 746 | */ |
| 747 | adapter->io_addr = io_addr; | 747 | host_adapter->io_addr = io_addr; |
| 748 | blogic_intreset(adapter); | 748 | blogic_intreset(host_adapter); |
| 749 | if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0, | 749 | if (blogic_cmd(host_adapter, BLOGIC_INQ_PCI_INFO, NULL, 0, |
| 750 | &adapter_info, sizeof(adapter_info)) == | 750 | &adapter_info, sizeof(adapter_info)) == |
| 751 | sizeof(adapter_info)) { | 751 | sizeof(adapter_info)) { |
| 752 | if (adapter_info.isa_port < 6) | 752 | if (adapter_info.isa_port < 6) |
| @@ -762,7 +762,7 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) | |||
| 762 | I/O Address assigned at system initialization. | 762 | I/O Address assigned at system initialization. |
| 763 | */ | 763 | */ |
| 764 | mod_ioaddr_req = BLOGIC_IO_DISABLE; | 764 | mod_ioaddr_req = BLOGIC_IO_DISABLE; |
| 765 | blogic_cmd(adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req, | 765 | blogic_cmd(host_adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req, |
| 766 | sizeof(mod_ioaddr_req), NULL, 0); | 766 | sizeof(mod_ioaddr_req), NULL, 0); |
| 767 | /* | 767 | /* |
| 768 | For the first MultiMaster Host Adapter enumerated, | 768 | For the first MultiMaster Host Adapter enumerated, |
| @@ -779,12 +779,12 @@ static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter) | |||
| 779 | 779 | ||
| 780 | fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45; | 780 | fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45; |
| 781 | fetch_localram.count = sizeof(autoscsi_byte45); | 781 | fetch_localram.count = sizeof(autoscsi_byte45); |
| 782 | blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM, | 782 | blogic_cmd(host_adapter, BLOGIC_FETCH_LOCALRAM, |
| 783 | &fetch_localram, sizeof(fetch_localram), | 783 | &fetch_localram, sizeof(fetch_localram), |
| 784 | &autoscsi_byte45, | 784 | &autoscsi_byte45, |
| 785 | sizeof(autoscsi_byte45)); | 785 | sizeof(autoscsi_byte45)); |
| 786 | blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id, | 786 | blogic_cmd(host_adapter, BLOGIC_GET_BOARD_ID, NULL, 0, |
| 787 | sizeof(id)); | 787 | &id, sizeof(id)); |
| 788 | if (id.fw_ver_digit1 == '5') | 788 | if (id.fw_ver_digit1 == '5') |
| 789 | force_scan_order = | 789 | force_scan_order = |
| 790 | autoscsi_byte45.force_scan_order; | 790 | autoscsi_byte45.force_scan_order; |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 408a42ef787a..f0d432c139d0 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
| @@ -771,6 +771,8 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long | |||
| 771 | static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | 771 | static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) |
| 772 | { | 772 | { |
| 773 | struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; | 773 | struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; |
| 774 | if (!capable(CAP_SYS_RAWIO)) | ||
| 775 | return -EPERM; | ||
| 774 | return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg); | 776 | return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg); |
| 775 | } | 777 | } |
| 776 | 778 | ||
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 2ef497ebadc0..ee5c1833eb73 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | * | Device Discovery | 0x2095 | 0x2020-0x2022, | | 20 | * | Device Discovery | 0x2095 | 0x2020-0x2022, | |
| 21 | * | | | 0x2011-0x2012, | | 21 | * | | | 0x2011-0x2012, | |
| 22 | * | | | 0x2016 | | 22 | * | | | 0x2016 | |
| 23 | * | Queue Command and IO tracing | 0x3058 | 0x3006-0x300b | | 23 | * | Queue Command and IO tracing | 0x3059 | 0x3006-0x300b | |
| 24 | * | | | 0x3027-0x3028 | | 24 | * | | | 0x3027-0x3028 | |
| 25 | * | | | 0x303d-0x3041 | | 25 | * | | | 0x303d-0x3041 | |
| 26 | * | | | 0x302d,0x3033 | | 26 | * | | | 0x302d,0x3033 | |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index df1b30ba938c..ff9c86b1a0d8 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
| @@ -1957,6 +1957,15 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
| 1957 | que = MSW(sts->handle); | 1957 | que = MSW(sts->handle); |
| 1958 | req = ha->req_q_map[que]; | 1958 | req = ha->req_q_map[que]; |
| 1959 | 1959 | ||
| 1960 | /* Check for invalid queue pointer */ | ||
| 1961 | if (req == NULL || | ||
| 1962 | que >= find_first_zero_bit(ha->req_qid_map, ha->max_req_queues)) { | ||
| 1963 | ql_dbg(ql_dbg_io, vha, 0x3059, | ||
| 1964 | "Invalid status handle (0x%x): Bad req pointer. req=%p, " | ||
| 1965 | "que=%u.\n", sts->handle, req, que); | ||
| 1966 | return; | ||
| 1967 | } | ||
| 1968 | |||
| 1960 | /* Validate handle. */ | 1969 | /* Validate handle. */ |
| 1961 | if (handle < req->num_outstanding_cmds) | 1970 | if (handle < req->num_outstanding_cmds) |
| 1962 | sp = req->outstanding_cmds[handle]; | 1971 | sp = req->outstanding_cmds[handle]; |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e62d17d41d4e..5693f6d7eddb 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -2854,6 +2854,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) | |||
| 2854 | gd->events |= DISK_EVENT_MEDIA_CHANGE; | 2854 | gd->events |= DISK_EVENT_MEDIA_CHANGE; |
| 2855 | } | 2855 | } |
| 2856 | 2856 | ||
| 2857 | blk_pm_runtime_init(sdp->request_queue, dev); | ||
| 2857 | add_disk(gd); | 2858 | add_disk(gd); |
| 2858 | if (sdkp->capacity) | 2859 | if (sdkp->capacity) |
| 2859 | sd_dif_config_host(sdkp); | 2860 | sd_dif_config_host(sdkp); |
| @@ -2862,7 +2863,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie) | |||
| 2862 | 2863 | ||
| 2863 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", | 2864 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", |
| 2864 | sdp->removable ? "removable " : ""); | 2865 | sdp->removable ? "removable " : ""); |
| 2865 | blk_pm_runtime_init(sdp->request_queue, dev); | ||
| 2866 | scsi_autopm_put_device(sdp); | 2866 | scsi_autopm_put_device(sdp); |
| 2867 | put_device(&sdkp->dev); | 2867 | put_device(&sdkp->dev); |
| 2868 | } | 2868 | } |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 5cbc4bb1b395..df5e961484e1 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
| @@ -105,8 +105,11 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ; | |||
| 105 | static int sg_add(struct device *, struct class_interface *); | 105 | static int sg_add(struct device *, struct class_interface *); |
| 106 | static void sg_remove(struct device *, struct class_interface *); | 106 | static void sg_remove(struct device *, struct class_interface *); |
| 107 | 107 | ||
| 108 | static DEFINE_SPINLOCK(sg_open_exclusive_lock); | ||
| 109 | |||
| 108 | static DEFINE_IDR(sg_index_idr); | 110 | static DEFINE_IDR(sg_index_idr); |
| 109 | static DEFINE_RWLOCK(sg_index_lock); | 111 | static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock |
| 112 | file descriptor list for device */ | ||
| 110 | 113 | ||
| 111 | static struct class_interface sg_interface = { | 114 | static struct class_interface sg_interface = { |
| 112 | .add_dev = sg_add, | 115 | .add_dev = sg_add, |
| @@ -143,7 +146,8 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ | |||
| 143 | } Sg_request; | 146 | } Sg_request; |
| 144 | 147 | ||
| 145 | typedef struct sg_fd { /* holds the state of a file descriptor */ | 148 | typedef struct sg_fd { /* holds the state of a file descriptor */ |
| 146 | struct list_head sfd_siblings; /* protected by sfd_lock of device */ | 149 | /* sfd_siblings is protected by sg_index_lock */ |
| 150 | struct list_head sfd_siblings; | ||
| 147 | struct sg_device *parentdp; /* owning device */ | 151 | struct sg_device *parentdp; /* owning device */ |
| 148 | wait_queue_head_t read_wait; /* queue read until command done */ | 152 | wait_queue_head_t read_wait; /* queue read until command done */ |
| 149 | rwlock_t rq_list_lock; /* protect access to list in req_arr */ | 153 | rwlock_t rq_list_lock; /* protect access to list in req_arr */ |
| @@ -166,12 +170,13 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ | |||
| 166 | 170 | ||
| 167 | typedef struct sg_device { /* holds the state of each scsi generic device */ | 171 | typedef struct sg_device { /* holds the state of each scsi generic device */ |
| 168 | struct scsi_device *device; | 172 | struct scsi_device *device; |
| 173 | wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ | ||
| 169 | int sg_tablesize; /* adapter's max scatter-gather table size */ | 174 | int sg_tablesize; /* adapter's max scatter-gather table size */ |
| 170 | u32 index; /* device index number */ | 175 | u32 index; /* device index number */ |
| 171 | spinlock_t sfd_lock; /* protect file descriptor list for device */ | 176 | /* sfds is protected by sg_index_lock */ |
| 172 | struct list_head sfds; | 177 | struct list_head sfds; |
| 173 | struct rw_semaphore o_sem; /* exclude open should hold this rwsem */ | ||
| 174 | volatile char detached; /* 0->attached, 1->detached pending removal */ | 178 | volatile char detached; /* 0->attached, 1->detached pending removal */ |
| 179 | /* exclude protected by sg_open_exclusive_lock */ | ||
| 175 | char exclude; /* opened for exclusive access */ | 180 | char exclude; /* opened for exclusive access */ |
| 176 | char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ | 181 | char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ |
| 177 | struct gendisk *disk; | 182 | struct gendisk *disk; |
| @@ -220,14 +225,35 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd) | |||
| 220 | return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE); | 225 | return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE); |
| 221 | } | 226 | } |
| 222 | 227 | ||
| 228 | static int get_exclude(Sg_device *sdp) | ||
| 229 | { | ||
| 230 | unsigned long flags; | ||
| 231 | int ret; | ||
| 232 | |||
| 233 | spin_lock_irqsave(&sg_open_exclusive_lock, flags); | ||
| 234 | ret = sdp->exclude; | ||
| 235 | spin_unlock_irqrestore(&sg_open_exclusive_lock, flags); | ||
| 236 | return ret; | ||
| 237 | } | ||
| 238 | |||
| 239 | static int set_exclude(Sg_device *sdp, char val) | ||
| 240 | { | ||
| 241 | unsigned long flags; | ||
| 242 | |||
| 243 | spin_lock_irqsave(&sg_open_exclusive_lock, flags); | ||
| 244 | sdp->exclude = val; | ||
| 245 | spin_unlock_irqrestore(&sg_open_exclusive_lock, flags); | ||
| 246 | return val; | ||
| 247 | } | ||
| 248 | |||
| 223 | static int sfds_list_empty(Sg_device *sdp) | 249 | static int sfds_list_empty(Sg_device *sdp) |
| 224 | { | 250 | { |
| 225 | unsigned long flags; | 251 | unsigned long flags; |
| 226 | int ret; | 252 | int ret; |
| 227 | 253 | ||
| 228 | spin_lock_irqsave(&sdp->sfd_lock, flags); | 254 | read_lock_irqsave(&sg_index_lock, flags); |
| 229 | ret = list_empty(&sdp->sfds); | 255 | ret = list_empty(&sdp->sfds); |
| 230 | spin_unlock_irqrestore(&sdp->sfd_lock, flags); | 256 | read_unlock_irqrestore(&sg_index_lock, flags); |
| 231 | return ret; | 257 | return ret; |
| 232 | } | 258 | } |
| 233 | 259 | ||
| @@ -239,6 +265,7 @@ sg_open(struct inode *inode, struct file *filp) | |||
| 239 | struct request_queue *q; | 265 | struct request_queue *q; |
| 240 | Sg_device *sdp; | 266 | Sg_device *sdp; |
| 241 | Sg_fd *sfp; | 267 | Sg_fd *sfp; |
| 268 | int res; | ||
| 242 | int retval; | 269 | int retval; |
| 243 | 270 | ||
| 244 | nonseekable_open(inode, filp); | 271 | nonseekable_open(inode, filp); |
| @@ -267,52 +294,54 @@ sg_open(struct inode *inode, struct file *filp) | |||
| 267 | goto error_out; | 294 | goto error_out; |
| 268 | } | 295 | } |
| 269 | 296 | ||
| 270 | if ((flags & O_EXCL) && (O_RDONLY == (flags & O_ACCMODE))) { | 297 | if (flags & O_EXCL) { |
| 271 | retval = -EPERM; /* Can't lock it with read only access */ | 298 | if (O_RDONLY == (flags & O_ACCMODE)) { |
| 272 | goto error_out; | 299 | retval = -EPERM; /* Can't lock it with read only access */ |
| 273 | } | 300 | goto error_out; |
| 274 | if (flags & O_NONBLOCK) { | 301 | } |
| 275 | if (flags & O_EXCL) { | 302 | if (!sfds_list_empty(sdp) && (flags & O_NONBLOCK)) { |
| 276 | if (!down_write_trylock(&sdp->o_sem)) { | 303 | retval = -EBUSY; |
| 277 | retval = -EBUSY; | 304 | goto error_out; |
| 278 | goto error_out; | 305 | } |
| 279 | } | 306 | res = wait_event_interruptible(sdp->o_excl_wait, |
| 280 | } else { | 307 | ((!sfds_list_empty(sdp) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1))); |
| 281 | if (!down_read_trylock(&sdp->o_sem)) { | 308 | if (res) { |
| 282 | retval = -EBUSY; | 309 | retval = res; /* -ERESTARTSYS because signal hit process */ |
| 283 | goto error_out; | 310 | goto error_out; |
| 284 | } | 311 | } |
| 312 | } else if (get_exclude(sdp)) { /* some other fd has an exclusive lock on dev */ | ||
| 313 | if (flags & O_NONBLOCK) { | ||
| 314 | retval = -EBUSY; | ||
| 315 | goto error_out; | ||
| 316 | } | ||
| 317 | res = wait_event_interruptible(sdp->o_excl_wait, !get_exclude(sdp)); | ||
| 318 | if (res) { | ||
| 319 | retval = res; /* -ERESTARTSYS because signal hit process */ | ||
| 320 | goto error_out; | ||
| 285 | } | 321 | } |
| 286 | } else { | ||
| 287 | if (flags & O_EXCL) | ||
| 288 | down_write(&sdp->o_sem); | ||
| 289 | else | ||
| 290 | down_read(&sdp->o_sem); | ||
| 291 | } | 322 | } |
| 292 | /* Since write lock is held, no need to check sfd_list */ | 323 | if (sdp->detached) { |
| 293 | if (flags & O_EXCL) | 324 | retval = -ENODEV; |
| 294 | sdp->exclude = 1; /* used by release lock */ | 325 | goto error_out; |
| 295 | 326 | } | |
| 296 | if (sfds_list_empty(sdp)) { /* no existing opens on this device */ | 327 | if (sfds_list_empty(sdp)) { /* no existing opens on this device */ |
| 297 | sdp->sgdebug = 0; | 328 | sdp->sgdebug = 0; |
| 298 | q = sdp->device->request_queue; | 329 | q = sdp->device->request_queue; |
| 299 | sdp->sg_tablesize = queue_max_segments(q); | 330 | sdp->sg_tablesize = queue_max_segments(q); |
| 300 | } | 331 | } |
| 301 | sfp = sg_add_sfp(sdp, dev); | 332 | if ((sfp = sg_add_sfp(sdp, dev))) |
| 302 | if (!IS_ERR(sfp)) | ||
| 303 | filp->private_data = sfp; | 333 | filp->private_data = sfp; |
| 304 | /* retval is already provably zero at this point because of the | ||
| 305 | * check after retval = scsi_autopm_get_device(sdp->device)) | ||
| 306 | */ | ||
| 307 | else { | 334 | else { |
| 308 | retval = PTR_ERR(sfp); | ||
| 309 | |||
| 310 | if (flags & O_EXCL) { | 335 | if (flags & O_EXCL) { |
| 311 | sdp->exclude = 0; /* undo if error */ | 336 | set_exclude(sdp, 0); /* undo if error */ |
| 312 | up_write(&sdp->o_sem); | 337 | wake_up_interruptible(&sdp->o_excl_wait); |
| 313 | } else | 338 | } |
| 314 | up_read(&sdp->o_sem); | 339 | retval = -ENOMEM; |
| 340 | goto error_out; | ||
| 341 | } | ||
| 342 | retval = 0; | ||
| 315 | error_out: | 343 | error_out: |
| 344 | if (retval) { | ||
| 316 | scsi_autopm_put_device(sdp->device); | 345 | scsi_autopm_put_device(sdp->device); |
| 317 | sdp_put: | 346 | sdp_put: |
| 318 | scsi_device_put(sdp->device); | 347 | scsi_device_put(sdp->device); |
| @@ -329,18 +358,13 @@ sg_release(struct inode *inode, struct file *filp) | |||
| 329 | { | 358 | { |
| 330 | Sg_device *sdp; | 359 | Sg_device *sdp; |
| 331 | Sg_fd *sfp; | 360 | Sg_fd *sfp; |
| 332 | int excl; | ||
| 333 | 361 | ||
| 334 | if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) | 362 | if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) |
| 335 | return -ENXIO; | 363 | return -ENXIO; |
| 336 | SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name)); | 364 | SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name)); |
| 337 | 365 | ||
| 338 | excl = sdp->exclude; | 366 | set_exclude(sdp, 0); |
| 339 | sdp->exclude = 0; | 367 | wake_up_interruptible(&sdp->o_excl_wait); |
| 340 | if (excl) | ||
| 341 | up_write(&sdp->o_sem); | ||
| 342 | else | ||
| 343 | up_read(&sdp->o_sem); | ||
| 344 | 368 | ||
| 345 | scsi_autopm_put_device(sdp->device); | 369 | scsi_autopm_put_device(sdp->device); |
| 346 | kref_put(&sfp->f_ref, sg_remove_sfp); | 370 | kref_put(&sfp->f_ref, sg_remove_sfp); |
| @@ -1391,9 +1415,8 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) | |||
| 1391 | disk->first_minor = k; | 1415 | disk->first_minor = k; |
| 1392 | sdp->disk = disk; | 1416 | sdp->disk = disk; |
| 1393 | sdp->device = scsidp; | 1417 | sdp->device = scsidp; |
| 1394 | spin_lock_init(&sdp->sfd_lock); | ||
| 1395 | INIT_LIST_HEAD(&sdp->sfds); | 1418 | INIT_LIST_HEAD(&sdp->sfds); |
| 1396 | init_rwsem(&sdp->o_sem); | 1419 | init_waitqueue_head(&sdp->o_excl_wait); |
| 1397 | sdp->sg_tablesize = queue_max_segments(q); | 1420 | sdp->sg_tablesize = queue_max_segments(q); |
| 1398 | sdp->index = k; | 1421 | sdp->index = k; |
| 1399 | kref_init(&sdp->d_ref); | 1422 | kref_init(&sdp->d_ref); |
| @@ -1526,13 +1549,11 @@ static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf) | |||
| 1526 | 1549 | ||
| 1527 | /* Need a write lock to set sdp->detached. */ | 1550 | /* Need a write lock to set sdp->detached. */ |
| 1528 | write_lock_irqsave(&sg_index_lock, iflags); | 1551 | write_lock_irqsave(&sg_index_lock, iflags); |
| 1529 | spin_lock(&sdp->sfd_lock); | ||
| 1530 | sdp->detached = 1; | 1552 | sdp->detached = 1; |
| 1531 | list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) { | 1553 | list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) { |
| 1532 | wake_up_interruptible(&sfp->read_wait); | 1554 | wake_up_interruptible(&sfp->read_wait); |
| 1533 | kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP); | 1555 | kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP); |
| 1534 | } | 1556 | } |
| 1535 | spin_unlock(&sdp->sfd_lock); | ||
| 1536 | write_unlock_irqrestore(&sg_index_lock, iflags); | 1557 | write_unlock_irqrestore(&sg_index_lock, iflags); |
| 1537 | 1558 | ||
| 1538 | sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); | 1559 | sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); |
| @@ -2043,7 +2064,7 @@ sg_add_sfp(Sg_device * sdp, int dev) | |||
| 2043 | 2064 | ||
| 2044 | sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN); | 2065 | sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN); |
| 2045 | if (!sfp) | 2066 | if (!sfp) |
| 2046 | return ERR_PTR(-ENOMEM); | 2067 | return NULL; |
| 2047 | 2068 | ||
| 2048 | init_waitqueue_head(&sfp->read_wait); | 2069 | init_waitqueue_head(&sfp->read_wait); |
| 2049 | rwlock_init(&sfp->rq_list_lock); | 2070 | rwlock_init(&sfp->rq_list_lock); |
| @@ -2057,13 +2078,9 @@ sg_add_sfp(Sg_device * sdp, int dev) | |||
| 2057 | sfp->cmd_q = SG_DEF_COMMAND_Q; | 2078 | sfp->cmd_q = SG_DEF_COMMAND_Q; |
| 2058 | sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; | 2079 | sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; |
| 2059 | sfp->parentdp = sdp; | 2080 | sfp->parentdp = sdp; |
| 2060 | spin_lock_irqsave(&sdp->sfd_lock, iflags); | 2081 | write_lock_irqsave(&sg_index_lock, iflags); |
| 2061 | if (sdp->detached) { | ||
| 2062 | spin_unlock_irqrestore(&sdp->sfd_lock, iflags); | ||
| 2063 | return ERR_PTR(-ENODEV); | ||
| 2064 | } | ||
| 2065 | list_add_tail(&sfp->sfd_siblings, &sdp->sfds); | 2082 | list_add_tail(&sfp->sfd_siblings, &sdp->sfds); |
| 2066 | spin_unlock_irqrestore(&sdp->sfd_lock, iflags); | 2083 | write_unlock_irqrestore(&sg_index_lock, iflags); |
| 2067 | SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp)); | 2084 | SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp)); |
| 2068 | if (unlikely(sg_big_buff != def_reserved_size)) | 2085 | if (unlikely(sg_big_buff != def_reserved_size)) |
| 2069 | sg_big_buff = def_reserved_size; | 2086 | sg_big_buff = def_reserved_size; |
| @@ -2113,9 +2130,10 @@ static void sg_remove_sfp(struct kref *kref) | |||
| 2113 | struct sg_device *sdp = sfp->parentdp; | 2130 | struct sg_device *sdp = sfp->parentdp; |
| 2114 | unsigned long iflags; | 2131 | unsigned long iflags; |
| 2115 | 2132 | ||
| 2116 | spin_lock_irqsave(&sdp->sfd_lock, iflags); | 2133 | write_lock_irqsave(&sg_index_lock, iflags); |
| 2117 | list_del(&sfp->sfd_siblings); | 2134 | list_del(&sfp->sfd_siblings); |
| 2118 | spin_unlock_irqrestore(&sdp->sfd_lock, iflags); | 2135 | write_unlock_irqrestore(&sg_index_lock, iflags); |
| 2136 | wake_up_interruptible(&sdp->o_excl_wait); | ||
| 2119 | 2137 | ||
| 2120 | INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext); | 2138 | INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext); |
| 2121 | schedule_work(&sfp->ew.work); | 2139 | schedule_work(&sfp->ew.work); |
| @@ -2502,7 +2520,7 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v) | |||
| 2502 | return 0; | 2520 | return 0; |
| 2503 | } | 2521 | } |
| 2504 | 2522 | ||
| 2505 | /* must be called while holding sg_index_lock and sfd_lock */ | 2523 | /* must be called while holding sg_index_lock */ |
| 2506 | static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) | 2524 | static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) |
| 2507 | { | 2525 | { |
| 2508 | int k, m, new_interface, blen, usg; | 2526 | int k, m, new_interface, blen, usg; |
| @@ -2587,26 +2605,22 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v) | |||
| 2587 | 2605 | ||
| 2588 | read_lock_irqsave(&sg_index_lock, iflags); | 2606 | read_lock_irqsave(&sg_index_lock, iflags); |
| 2589 | sdp = it ? sg_lookup_dev(it->index) : NULL; | 2607 | sdp = it ? sg_lookup_dev(it->index) : NULL; |
| 2590 | if (sdp) { | 2608 | if (sdp && !list_empty(&sdp->sfds)) { |
| 2591 | spin_lock(&sdp->sfd_lock); | 2609 | struct scsi_device *scsidp = sdp->device; |
| 2592 | if (!list_empty(&sdp->sfds)) { | ||
| 2593 | struct scsi_device *scsidp = sdp->device; | ||
| 2594 | 2610 | ||
| 2595 | seq_printf(s, " >>> device=%s ", sdp->disk->disk_name); | 2611 | seq_printf(s, " >>> device=%s ", sdp->disk->disk_name); |
| 2596 | if (sdp->detached) | 2612 | if (sdp->detached) |
| 2597 | seq_printf(s, "detached pending close "); | 2613 | seq_printf(s, "detached pending close "); |
| 2598 | else | 2614 | else |
| 2599 | seq_printf | 2615 | seq_printf |
| 2600 | (s, "scsi%d chan=%d id=%d lun=%d em=%d", | 2616 | (s, "scsi%d chan=%d id=%d lun=%d em=%d", |
| 2601 | scsidp->host->host_no, | 2617 | scsidp->host->host_no, |
| 2602 | scsidp->channel, scsidp->id, | 2618 | scsidp->channel, scsidp->id, |
| 2603 | scsidp->lun, | 2619 | scsidp->lun, |
| 2604 | scsidp->host->hostt->emulated); | 2620 | scsidp->host->hostt->emulated); |
| 2605 | seq_printf(s, " sg_tablesize=%d excl=%d\n", | 2621 | seq_printf(s, " sg_tablesize=%d excl=%d\n", |
| 2606 | sdp->sg_tablesize, sdp->exclude); | 2622 | sdp->sg_tablesize, get_exclude(sdp)); |
| 2607 | sg_proc_debug_helper(s, sdp); | 2623 | sg_proc_debug_helper(s, sdp); |
| 2608 | } | ||
| 2609 | spin_unlock(&sdp->sfd_lock); | ||
| 2610 | } | 2624 | } |
| 2611 | read_unlock_irqrestore(&sg_index_lock, iflags); | 2625 | read_unlock_irqrestore(&sg_index_lock, iflags); |
| 2612 | return 0; | 2626 | return 0; |
