aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/dpt_i2o.c25
-rw-r--r--drivers/scsi/libata-scsi.c5
-rw-r--r--drivers/scsi/scsi_scan.c49
-rw-r--r--drivers/scsi/scsi_transport_fc.c59
4 files changed, 115 insertions, 23 deletions
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 418fc7b896ac..6252b9ddc01e 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -660,7 +660,12 @@ static int adpt_abort(struct scsi_cmnd * cmd)
660 msg[2] = 0; 660 msg[2] = 0;
661 msg[3]= 0; 661 msg[3]= 0;
662 msg[4] = (u32)cmd; 662 msg[4] = (u32)cmd;
663 if( (rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER)) != 0){ 663 if (pHba->host)
664 spin_lock_irq(pHba->host->host_lock);
665 rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER);
666 if (pHba->host)
667 spin_unlock_irq(pHba->host->host_lock);
668 if (rcode != 0) {
664 if(rcode == -EOPNOTSUPP ){ 669 if(rcode == -EOPNOTSUPP ){
665 printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name); 670 printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name);
666 return FAILED; 671 return FAILED;
@@ -697,10 +702,15 @@ static int adpt_device_reset(struct scsi_cmnd* cmd)
697 msg[2] = 0; 702 msg[2] = 0;
698 msg[3] = 0; 703 msg[3] = 0;
699 704
705 if (pHba->host)
706 spin_lock_irq(pHba->host->host_lock);
700 old_state = d->state; 707 old_state = d->state;
701 d->state |= DPTI_DEV_RESET; 708 d->state |= DPTI_DEV_RESET;
702 if( (rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER)) ){ 709 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
703 d->state = old_state; 710 d->state = old_state;
711 if (pHba->host)
712 spin_unlock_irq(pHba->host->host_lock);
713 if (rcode != 0) {
704 if(rcode == -EOPNOTSUPP ){ 714 if(rcode == -EOPNOTSUPP ){
705 printk(KERN_INFO"%s: Device reset not supported\n",pHba->name); 715 printk(KERN_INFO"%s: Device reset not supported\n",pHba->name);
706 return FAILED; 716 return FAILED;
@@ -708,7 +718,6 @@ static int adpt_device_reset(struct scsi_cmnd* cmd)
708 printk(KERN_INFO"%s: Device reset failed\n",pHba->name); 718 printk(KERN_INFO"%s: Device reset failed\n",pHba->name);
709 return FAILED; 719 return FAILED;
710 } else { 720 } else {
711 d->state = old_state;
712 printk(KERN_INFO"%s: Device reset successful\n",pHba->name); 721 printk(KERN_INFO"%s: Device reset successful\n",pHba->name);
713 return SUCCESS; 722 return SUCCESS;
714 } 723 }
@@ -721,6 +730,7 @@ static int adpt_bus_reset(struct scsi_cmnd* cmd)
721{ 730{
722 adpt_hba* pHba; 731 adpt_hba* pHba;
723 u32 msg[4]; 732 u32 msg[4];
733 u32 rcode;
724 734
725 pHba = (adpt_hba*)cmd->device->host->hostdata[0]; 735 pHba = (adpt_hba*)cmd->device->host->hostdata[0];
726 memset(msg, 0, sizeof(msg)); 736 memset(msg, 0, sizeof(msg));
@@ -729,7 +739,12 @@ static int adpt_bus_reset(struct scsi_cmnd* cmd)
729 msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid); 739 msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid);
730 msg[2] = 0; 740 msg[2] = 0;
731 msg[3] = 0; 741 msg[3] = 0;
732 if(adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER) ){ 742 if (pHba->host)
743 spin_lock_irq(pHba->host->host_lock);
744 rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER);
745 if (pHba->host)
746 spin_unlock_irq(pHba->host->host_lock);
747 if (rcode != 0) {
733 printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name); 748 printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name);
734 return FAILED; 749 return FAILED;
735 } else { 750 } else {
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 72ddba98f8fb..2282c04fee46 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -2044,7 +2044,7 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
2044 else { 2044 else {
2045 u8 *scsicmd = cmd->cmnd; 2045 u8 *scsicmd = cmd->cmnd;
2046 2046
2047 if (scsicmd[0] == INQUIRY) { 2047 if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
2048 u8 *buf = NULL; 2048 u8 *buf = NULL;
2049 unsigned int buflen; 2049 unsigned int buflen;
2050 2050
@@ -2058,9 +2058,6 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
2058 * device. 2) Ensure response data format / ATAPI information 2058 * device. 2) Ensure response data format / ATAPI information
2059 * are always correct. 2059 * are always correct.
2060 */ 2060 */
2061 /* FIXME: do we ever override EVPD pages and the like, with
2062 * this code?
2063 */
2064 if (buf[2] == 0) { 2061 if (buf[2] == 0) {
2065 buf[2] = 0x5; 2062 buf[2] = 0x5;
2066 buf[3] = 0x32; 2063 buf[3] = 0x32;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 950b087e4ca2..05ebb9cef961 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -400,6 +400,36 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
400 return found_target; 400 return found_target;
401} 401}
402 402
403struct work_queue_wrapper {
404 struct work_struct work;
405 struct scsi_target *starget;
406};
407
408static void scsi_target_reap_work(void *data) {
409 struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
410 struct scsi_target *starget = wqw->starget;
411 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
412 unsigned long flags;
413
414 kfree(wqw);
415
416 spin_lock_irqsave(shost->host_lock, flags);
417
418 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
419 list_del_init(&starget->siblings);
420 spin_unlock_irqrestore(shost->host_lock, flags);
421 transport_remove_device(&starget->dev);
422 device_del(&starget->dev);
423 transport_destroy_device(&starget->dev);
424 put_device(&starget->dev);
425 return;
426
427 }
428 spin_unlock_irqrestore(shost->host_lock, flags);
429
430 return;
431}
432
403/** 433/**
404 * scsi_target_reap - check to see if target is in use and destroy if not 434 * scsi_target_reap - check to see if target is in use and destroy if not
405 * 435 *
@@ -411,19 +441,18 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
411 */ 441 */
412void scsi_target_reap(struct scsi_target *starget) 442void scsi_target_reap(struct scsi_target *starget)
413{ 443{
414 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 444 struct work_queue_wrapper *wqw =
415 unsigned long flags; 445 kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
416 spin_lock_irqsave(shost->host_lock, flags);
417 446
418 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { 447 if (!wqw) {
419 list_del_init(&starget->siblings); 448 starget_printk(KERN_ERR, starget,
420 spin_unlock_irqrestore(shost->host_lock, flags); 449 "Failed to allocate memory in scsi_reap_target()\n");
421 device_del(&starget->dev);
422 transport_unregister_device(&starget->dev);
423 put_device(&starget->dev);
424 return; 450 return;
425 } 451 }
426 spin_unlock_irqrestore(shost->host_lock, flags); 452
453 INIT_WORK(&wqw->work, scsi_target_reap_work, wqw);
454 wqw->starget = starget;
455 schedule_work(&wqw->work);
427} 456}
428 457
429/** 458/**
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index cd95d2ae7b77..685b997306cf 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -105,6 +105,7 @@ static struct {
105 { FC_PORTSTATE_LINKDOWN, "Linkdown" }, 105 { FC_PORTSTATE_LINKDOWN, "Linkdown" },
106 { FC_PORTSTATE_ERROR, "Error" }, 106 { FC_PORTSTATE_ERROR, "Error" },
107 { FC_PORTSTATE_LOOPBACK, "Loopback" }, 107 { FC_PORTSTATE_LOOPBACK, "Loopback" },
108 { FC_PORTSTATE_DELETED, "Deleted" },
108}; 109};
109fc_enum_name_search(port_state, fc_port_state, fc_port_state_names) 110fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
110#define FC_PORTSTATE_MAX_NAMELEN 20 111#define FC_PORTSTATE_MAX_NAMELEN 20
@@ -211,6 +212,7 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
211#define FC_MGMTSRVR_PORTID 0x00000a 212#define FC_MGMTSRVR_PORTID 0x00000a
212 213
213 214
215static void fc_shost_remove_rports(void *data);
214static void fc_timeout_deleted_rport(void *data); 216static void fc_timeout_deleted_rport(void *data);
215static void fc_scsi_scan_rport(void *data); 217static void fc_scsi_scan_rport(void *data);
216static void fc_rport_terminate(struct fc_rport *rport); 218static void fc_rport_terminate(struct fc_rport *rport);
@@ -318,6 +320,8 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
318 fc_host_next_rport_number(shost) = 0; 320 fc_host_next_rport_number(shost) = 0;
319 fc_host_next_target_id(shost) = 0; 321 fc_host_next_target_id(shost) = 0;
320 322
323 fc_host_flags(shost) = 0;
324 INIT_WORK(&fc_host_rport_del_work(shost), fc_shost_remove_rports, shost);
321 return 0; 325 return 0;
322} 326}
323 327
@@ -387,6 +391,7 @@ show_fc_rport_##field (struct class_device *cdev, char *buf) \
387 struct fc_internal *i = to_fc_internal(shost->transportt); \ 391 struct fc_internal *i = to_fc_internal(shost->transportt); \
388 if ((i->f->get_rport_##field) && \ 392 if ((i->f->get_rport_##field) && \
389 !((rport->port_state == FC_PORTSTATE_BLOCKED) || \ 393 !((rport->port_state == FC_PORTSTATE_BLOCKED) || \
394 (rport->port_state == FC_PORTSTATE_DELETED) || \
390 (rport->port_state == FC_PORTSTATE_NOTPRESENT))) \ 395 (rport->port_state == FC_PORTSTATE_NOTPRESENT))) \
391 i->f->get_rport_##field(rport); \ 396 i->f->get_rport_##field(rport); \
392 return snprintf(buf, sz, format_string, cast rport->field); \ 397 return snprintf(buf, sz, format_string, cast rport->field); \
@@ -402,6 +407,7 @@ store_fc_rport_##field(struct class_device *cdev, const char *buf, \
402 struct Scsi_Host *shost = rport_to_shost(rport); \ 407 struct Scsi_Host *shost = rport_to_shost(rport); \
403 struct fc_internal *i = to_fc_internal(shost->transportt); \ 408 struct fc_internal *i = to_fc_internal(shost->transportt); \
404 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \ 409 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \
410 (rport->port_state == FC_PORTSTATE_DELETED) || \
405 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) \ 411 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) \
406 return -EBUSY; \ 412 return -EBUSY; \
407 val = simple_strtoul(buf, NULL, 0); \ 413 val = simple_strtoul(buf, NULL, 0); \
@@ -519,6 +525,7 @@ store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
519 struct Scsi_Host *shost = rport_to_shost(rport); 525 struct Scsi_Host *shost = rport_to_shost(rport);
520 struct fc_internal *i = to_fc_internal(shost->transportt); 526 struct fc_internal *i = to_fc_internal(shost->transportt);
521 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || 527 if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
528 (rport->port_state == FC_PORTSTATE_DELETED) ||
522 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) 529 (rport->port_state == FC_PORTSTATE_NOTPRESENT))
523 return -EBUSY; 530 return -EBUSY;
524 val = simple_strtoul(buf, NULL, 0); 531 val = simple_strtoul(buf, NULL, 0);
@@ -1769,7 +1776,7 @@ fc_timeout_deleted_rport(void *data)
1769 rport->maxframe_size = -1; 1776 rport->maxframe_size = -1;
1770 rport->supported_classes = FC_COS_UNSPECIFIED; 1777 rport->supported_classes = FC_COS_UNSPECIFIED;
1771 rport->roles = FC_RPORT_ROLE_UNKNOWN; 1778 rport->roles = FC_RPORT_ROLE_UNKNOWN;
1772 rport->port_state = FC_PORTSTATE_NOTPRESENT; 1779 rport->port_state = FC_PORTSTATE_DELETED;
1773 1780
1774 /* remove the identifiers that aren't used in the consisting binding */ 1781 /* remove the identifiers that aren't used in the consisting binding */
1775 switch (fc_host_tgtid_bind_type(shost)) { 1782 switch (fc_host_tgtid_bind_type(shost)) {
@@ -1789,14 +1796,23 @@ fc_timeout_deleted_rport(void *data)
1789 break; 1796 break;
1790 } 1797 }
1791 1798
1792 spin_unlock_irqrestore(shost->host_lock, flags);
1793
1794 /* 1799 /*
1795 * As this only occurs if the remote port (scsi target) 1800 * As this only occurs if the remote port (scsi target)
1796 * went away and didn't come back - we'll remove 1801 * went away and didn't come back - we'll remove
1797 * all attached scsi devices. 1802 * all attached scsi devices.
1803 *
1804 * We'll schedule the shost work item to perform the actual removal
1805 * to avoid recursion in the different flush calls if we perform
1806 * the removal in each target - and there are lots of targets
1807 * whose timeouts fire at the same time.
1798 */ 1808 */
1799 fc_rport_tgt_remove(rport); 1809
1810 if ( !(fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED)) {
1811 fc_host_flags(shost) |= FC_SHOST_RPORT_DEL_SCHEDULED;
1812 scsi_queue_work(shost, &fc_host_rport_del_work(shost));
1813 }
1814
1815 spin_unlock_irqrestore(shost->host_lock, flags);
1800} 1816}
1801 1817
1802/** 1818/**
@@ -1818,6 +1834,41 @@ fc_scsi_scan_rport(void *data)
1818} 1834}
1819 1835
1820 1836
1837/**
1838 * fc_shost_remove_rports - called to remove all rports that are marked
1839 * as in a deleted (not connected) state.
1840 *
1841 * @data: shost whose rports are to be looked at
1842 **/
1843static void
1844fc_shost_remove_rports(void *data)
1845{
1846 struct Scsi_Host *shost = (struct Scsi_Host *)data;
1847 struct fc_rport *rport, *next_rport;
1848 unsigned long flags;
1849
1850 spin_lock_irqsave(shost->host_lock, flags);
1851 while (fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED) {
1852
1853 fc_host_flags(shost) &= ~FC_SHOST_RPORT_DEL_SCHEDULED;
1854
1855restart_search:
1856 list_for_each_entry_safe(rport, next_rport,
1857 &fc_host_rport_bindings(shost), peers) {
1858 if (rport->port_state == FC_PORTSTATE_DELETED) {
1859 rport->port_state = FC_PORTSTATE_NOTPRESENT;
1860 spin_unlock_irqrestore(shost->host_lock, flags);
1861 fc_rport_tgt_remove(rport);
1862 spin_lock_irqsave(shost->host_lock, flags);
1863 goto restart_search;
1864 }
1865 }
1866
1867 }
1868 spin_unlock_irqrestore(shost->host_lock, flags);
1869}
1870
1871
1821MODULE_AUTHOR("Martin Hicks"); 1872MODULE_AUTHOR("Martin Hicks");
1822MODULE_DESCRIPTION("FC Transport Attributes"); 1873MODULE_DESCRIPTION("FC Transport Attributes");
1823MODULE_LICENSE("GPL"); 1874MODULE_LICENSE("GPL");