[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#364725: kernel-source-2.6.8: IEEE1394 SBP2 disconnect problems



Package: kernel-source-2.6.8
Version: 2.6.8-16sarge2
Severity: important
Tags: patch

SBP2 causes problems when disconnecting devices such as CDROMs.
Sometimes, the system will hang when trying to suspend to disk or
unloading the IEEE1394 modules, sometimes it will hang when typing

  cat /proc/scsi/scsi

after unplugging a firewire SBP2 device.

I had a look at the kernel changes to sbp2.c and found a bunch of
changes which seemed related to my problem. I added them incrementally
on top of the official Debian Sarge 2.6.8 kernel and all [my] problems
were gone. I believe the changes are safe and others would benefit from
them as well.

I have attached a patch with the changes. All those changes were
back-ported from kernel.org, thus there's no invention (or crap ;) from
my side.

Thanks,
--Christian



-- System Information:
Debian Release: 3.1
Architecture: i386 (i686)
Kernel: Linux 2.6.8-cm1.1
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages kernel-source-2.6.8 depends on:
ii  binutils                      2.15-6     The GNU assembler, linker and bina
ii  bzip2                         1.0.2-7    high-quality block-sorting file co
ii  coreutils [fileutils]         5.2.1-2    The GNU core utilities

-- no debconf information
*** sbp2.c.orig	Tue Apr 11 14:52:44 2006

--- sbp2.c	Tue Apr 11 14:52:23 2006

***************

*** 593,598 ****

--- 593,605 ----

  	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);

  }

  

+ /*

+  * Is scsi_id valid? Is the 1394 node still present?

+  */

+ static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_id)

+ {

+ 	return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo;

+ }

  

  

  /*********************************************

***************

*** 628,638 ****

--- 635,657 ----

  {

  	struct unit_directory *ud;

  	struct scsi_id_instance_data *scsi_id;

+ 	struct scsi_device *sdev;

  

  	SBP2_DEBUG("sbp2_remove");

  

  	ud = container_of(dev, struct unit_directory, device);

  	scsi_id = ud->device.driver_data;

+ 	if (!scsi_id)

+ 		return 0;

+ 

+ 	/* trigger shutdown functions in scsi's highlevel */

+ 	if (scsi_id->scsi_host)

+ 		scsi_unblock_requests(scsi_id->scsi_host);

+ 	sdev = scsi_id->sdev;

+ 	if (sdev) {

+ 		scsi_id->sdev = NULL;

+ 		scsi_remove_device(sdev);

+ 	}

  

  	sbp2_logout_device(scsi_id);

  	sbp2_remove_device(scsi_id);

***************

*** 743,749 ****

  	list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);

  

  	/* Register our host with the SCSI stack. */

! 	scsi_host = scsi_host_alloc(&scsi_driver_template, 0);

  	if (!scsi_host) {

  		SBP2_ERR("failed to register scsi host");

  		goto failed_alloc;

--- 762,769 ----

  	list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);

  

  	/* Register our host with the SCSI stack. */

! 	scsi_host = scsi_host_alloc(&scsi_driver_template,

! 				    sizeof (unsigned long));

  	if (!scsi_host) {

  		SBP2_ERR("failed to register scsi host");

  		goto failed_alloc;

***************

*** 2460,2496 ****

  	struct scsi_id_instance_data *scsi_id =

  		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];

  	struct sbp2scsi_host_info *hi;

  

  	SBP2_DEBUG("sbp2scsi_queuecommand");

  

! 	/*

! 	 * If scsi_id is null, it means there is no device in this slot,

! 	 * so we should return selection timeout.

! 	 */

! 	if (!scsi_id) {

! 		SCpnt->result = DID_NO_CONNECT << 16;

! 		done (SCpnt);

! 		return 0;

! 	}

  

  	hi = scsi_id->hi;

  

  	if (!hi) {

  		SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");

! 		SCpnt->result = DID_NO_CONNECT << 16;

! 		done (SCpnt);

! 		return(0);

  	}

  

  	/*

  	 * Until we handle multiple luns, just return selection time-out

  	 * to any IO directed at non-zero LUNs

  	 */

! 	if (SCpnt->device->lun) {

! 		SCpnt->result = DID_NO_CONNECT << 16;

! 		done (SCpnt);

! 		return(0);

! 	}

  

  	/*

  	 * Check for request sense command, and handle it here

--- 2480,2505 ----

  	struct scsi_id_instance_data *scsi_id =

  		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];

  	struct sbp2scsi_host_info *hi;

+ 	int result = DID_NO_CONNECT << 16;

  

  	SBP2_DEBUG("sbp2scsi_queuecommand");

  

! 	if (!sbp2util_node_is_available(scsi_id))

! 		goto done;

  

  	hi = scsi_id->hi;

  

  	if (!hi) {

  		SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");

! 		goto done;

  	}

  

  	/*

  	 * Until we handle multiple luns, just return selection time-out

  	 * to any IO directed at non-zero LUNs

  	 */

! 	if (SCpnt->device->lun)

! 		goto done;

  

  	/*

  	 * Check for request sense command, and handle it here

***************

*** 2501,2507 ****

  		memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen);

  		memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));

  		sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done);

! 		return(0);

  	}

  

  	/*

--- 2510,2516 ----

  		memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen);

  		memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));

  		sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done);

! 		return 0;

  	}

  

  	/*

***************

*** 2509,2517 ****

  	 */

  	if (!hpsb_node_entry_valid(scsi_id->ne)) {

  		SBP2_ERR("Bus reset in progress - rejecting command");

! 		SCpnt->result = DID_BUS_BUSY << 16;

! 		done (SCpnt);

! 		return(0);

  	}

  

  	/*

--- 2518,2525 ----

  	 */

  	if (!hpsb_node_entry_valid(scsi_id->ne)) {

  		SBP2_ERR("Bus reset in progress - rejecting command");

! 		result = DID_BUS_BUSY << 16;

! 		goto done;

  	}

  

  	/*

***************

*** 2523,2529 ****

  					  SCpnt, done);

  	}

  

! 	return(0);

  }

  

  /*

--- 2531,2542 ----

  					  SCpnt, done);

  	}

  

! 	return 0;

! 

! done:

! 	SCpnt->result = result;

! 	done(SCpnt);

! 	return 0;

  }

  

  /*

***************

*** 2569,2576 ****

  				      u32 scsi_status, Scsi_Cmnd *SCpnt,

  				      void (*done)(Scsi_Cmnd *))

  {

- 	unsigned long flags;

- 

  	SBP2_DEBUG("sbp2scsi_complete_command");

  

  	/*

--- 2582,2587 ----

***************

*** 2669,2689 ****

  	/*

  	 * Tell scsi stack that we're done with this command

  	 */

- 	spin_lock_irqsave(scsi_id->scsi_host->host_lock,flags);

  	done (SCpnt);

- 	spin_unlock_irqrestore(scsi_id->scsi_host->host_lock,flags);

  

  	return;

  }

  

  

  static int sbp2scsi_slave_configure (struct scsi_device *sdev)

  {

  	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));

- 

  	return 0;

  }

  

  

  /*

   * Called by scsi stack when something has really gone wrong.  Usually

--- 2680,2708 ----

  	/*

  	 * Tell scsi stack that we're done with this command

  	 */

  	done (SCpnt);

  

  	return;

  }

  

+ static int sbp2scsi_slave_alloc (struct scsi_device *sdev)

+ {

+ 	((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev;

+ 	return 0;

+ }

  

  static int sbp2scsi_slave_configure (struct scsi_device *sdev)

  {

  	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));

  	return 0;

  }

  

+ static void sbp2scsi_slave_destroy (struct scsi_device *sdev)

+ {

+ 	((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL;

+ 	return;

+ }

+ 

  

  /*

   * Called by scsi stack when something has really gone wrong.  Usually

***************

*** 2699,2705 ****

  	SBP2_ERR("aborting sbp2 command");

  	print_command (SCpnt->cmnd);

  

! 	if (scsi_id) {

  

  		/*

  		 * Right now, just return any matching command structures

--- 2718,2724 ----

  	SBP2_ERR("aborting sbp2 command");

  	print_command (SCpnt->cmnd);

  

! 	if (sbp2util_node_is_available(scsi_id)) {

  

  		/*

  		 * Right now, just return any matching command structures

***************

*** 2741,2753 ****

  {

  	struct scsi_id_instance_data *scsi_id =

  		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];

  

  	SBP2_ERR("reset requested");

  

! 	if (scsi_id) {

  		SBP2_ERR("Generating sbp2 fetch agent reset");

  		sbp2_agent_reset(scsi_id, 0);

  	}

  

  	return(SUCCESS);

  }

--- 2760,2775 ----

  {

  	struct scsi_id_instance_data *scsi_id =

  		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];

+ 	unsigned long flags;

  

  	SBP2_ERR("reset requested");

  

! 	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);

! 	if (sbp2util_node_is_available(scsi_id)) {

  		SBP2_ERR("Generating sbp2 fetch agent reset");

  		sbp2_agent_reset(scsi_id, 0);

  	}

+ 	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);

  

  	return(SUCCESS);

  }

***************

*** 2800,2806 ****

--- 2822,2830 ----

  	.eh_device_reset_handler =	sbp2scsi_reset,

  	.eh_bus_reset_handler =		sbp2scsi_reset,

  	.eh_host_reset_handler =	sbp2scsi_reset,

+ 	.slave_alloc =			sbp2scsi_slave_alloc,

  	.slave_configure =		sbp2scsi_slave_configure,

+ 	.slave_destroy =		sbp2scsi_slave_destroy,

  	.this_id =			-1,

  	.sg_tablesize =			SG_ALL,

  	.use_clustering =		ENABLE_CLUSTERING,


Reply to: