diff options
Diffstat (limited to 'drivers/staging/rts5139/rts51x.c')
| -rw-r--r-- | drivers/staging/rts5139/rts51x.c | 858 | 
1 files changed, 0 insertions, 858 deletions
diff --git a/drivers/staging/rts5139/rts51x.c b/drivers/staging/rts5139/rts51x.c deleted file mode 100644 index 04213463123..00000000000 --- a/drivers/staging/rts5139/rts51x.c +++ /dev/null @@ -1,858 +0,0 @@ -/* Driver for Realtek RTS51xx USB card reader - * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - * - * Author: - *   wwang (wei_wang@realsil.com.cn) - *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - * Maintainer: - *   Edwin Rong (edwin_rong@realsil.com.cn) - *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/workqueue.h> -#include <linux/errno.h> -#include <linux/freezer.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/utsname.h> -#include <linux/usb.h> - -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_devinfo.h> -#include <scsi/scsi_eh.h> -#include <scsi/scsi_host.h> - -#include "debug.h" -#include "ms.h" -#include "rts51x.h" -#include "rts51x_chip.h" -#include "rts51x_card.h" -#include "rts51x_scsi.h" -#include "rts51x_transport.h" -#include "rts51x_fop.h" - -MODULE_DESCRIPTION(RTS51X_DESC); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRIVER_VERSION); - -static int auto_delink_en; -module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); - -static int ss_en; -module_param(ss_en, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ss_en, "enable selective suspend"); - -static int ss_delay = 50; -module_param(ss_delay, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ss_delay, -		 "seconds to delay before entering selective suspend"); - -static int needs_remote_wakeup; -module_param(needs_remote_wakeup, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(needs_remote_wakeup, "ss state needs remote wakeup supported"); - -#ifdef SUPPORT_FILE_OP -static const struct file_operations rts51x_fops = { -	.owner = THIS_MODULE, -	.read = rts51x_read, -	.write = rts51x_write, -	.unlocked_ioctl = rts51x_ioctl, -	.open = rts51x_open, -	.release = rts51x_release, -}; - -/* - * usb class driver info in order to get a minor number from the usb core, - * and to have the device registered with the driver core - */ -static struct usb_class_driver rts51x_class = { -	.name = "rts51x%d", -	.fops = &rts51x_fops, -	.minor_base = 192, -}; -#endif - -#ifdef CONFIG_PM		/* Minimal support for suspend and resume */ - -static inline void usb_autopm_enable(struct usb_interface *intf) -{ -	atomic_set(&intf->pm_usage_cnt, 1); -	usb_autopm_put_interface(intf); -} - -static inline void usb_autopm_disable(struct usb_interface *intf) -{ -	atomic_set(&intf->pm_usage_cnt, 0); -	usb_autopm_get_interface(intf); -} - -static void rts51x_try_to_enter_ss(struct rts51x_chip *chip) -{ -	RTS51X_DEBUGP("Ready to enter SS state\n"); -	usb_autopm_enable(chip->usb->pusb_intf); -} - -void rts51x_try_to_exit_ss(struct rts51x_chip *chip) -{ -	RTS51X_DEBUGP("Exit from SS state\n"); -	usb_autopm_disable(chip->usb->pusb_intf); -} - -int rts51x_suspend(struct usb_interface *iface, pm_message_t message) -{ -	struct rts51x_chip *chip = usb_get_intfdata(iface); - -	RTS51X_DEBUGP("%s, message.event = 0x%x\n", __func__, message.event); - -	/* Wait until no command is running */ -	mutex_lock(&chip->usb->dev_mutex); - -	chip->fake_card_ready = chip->card_ready; -	rts51x_do_before_power_down(chip); - -	if (message.event == PM_EVENT_AUTO_SUSPEND) { -		RTS51X_DEBUGP("Enter SS state"); -		chip->resume_from_scsi = 0; -		RTS51X_SET_STAT(chip, STAT_SS); -	} else { -		RTS51X_DEBUGP("Enter SUSPEND state"); -		RTS51X_SET_STAT(chip, STAT_SUSPEND); -	} - -	/* When runtime PM is working, we'll set a flag to indicate -	 * whether we should autoresume when a SCSI request arrives. */ - -	mutex_unlock(&chip->usb->dev_mutex); -	return 0; -} - -int rts51x_resume(struct usb_interface *iface) -{ -	struct rts51x_chip *chip = usb_get_intfdata(iface); - -	RTS51X_DEBUGP("%s\n", __func__); - -	if (!RTS51X_CHK_STAT(chip, STAT_SS) || !chip->resume_from_scsi) { -		mutex_lock(&chip->usb->dev_mutex); - -		if (chip->option.ss_en) { -			if (GET_PM_USAGE_CNT(chip) <= 0) { -				/* Remote wake up, increase pm_usage_cnt */ -				RTS51X_DEBUGP("Incr pm_usage_cnt\n"); -				SET_PM_USAGE_CNT(chip, 1); -			} -		} - -		RTS51X_SET_STAT(chip, STAT_RUN); - -		rts51x_init_chip(chip); -		rts51x_init_cards(chip); - -		mutex_unlock(&chip->usb->dev_mutex); -	} - -	return 0; -} - -int rts51x_reset_resume(struct usb_interface *iface) -{ -	struct rts51x_chip *chip = usb_get_intfdata(iface); - -	RTS51X_DEBUGP("%s\n", __func__); - -	mutex_lock(&chip->usb->dev_mutex); - -	RTS51X_SET_STAT(chip, STAT_RUN); - -	if (chip->option.ss_en) -		SET_PM_USAGE_CNT(chip, 1); - -	rts51x_init_chip(chip); -	rts51x_init_cards(chip); - -	mutex_unlock(&chip->usb->dev_mutex); - -	/* FIXME: Notify the subdrivers that they need to reinitialize -	 * the device */ -	return 0; -} - -#else /* CONFIG_PM */ - -static void rts51x_try_to_enter_ss(struct rts51x_chip *chip) -{ -} - -void rts51x_try_to_exit_ss(struct rts51x_chip *chip) -{ -} - -#endif /* CONFIG_PM */ - -/* - * The next two routines get called just before and just after - * a USB port reset, whether from this driver or a different one. - */ - -int rts51x_pre_reset(struct usb_interface *iface) -{ -	struct rts51x_chip *chip = usb_get_intfdata(iface); - -	RTS51X_DEBUGP("%s\n", __func__); - -	/* Make sure no command runs during the reset */ -	mutex_lock(&chip->usb->dev_mutex); -	return 0; -} - -int rts51x_post_reset(struct usb_interface *iface) -{ -	struct rts51x_chip *chip = usb_get_intfdata(iface); - -	RTS51X_DEBUGP("%s\n", __func__); - -	/* Report the reset to the SCSI core */ -	/* usb_stor_report_bus_reset(us); */ - -	/* FIXME: Notify the subdrivers that they need to reinitialize -	 * the device */ - -	mutex_unlock(&chip->usb->dev_mutex); -	return 0; -} - -static int rts51x_control_thread(void *__chip) -{ -	struct rts51x_chip *chip = (struct rts51x_chip *)__chip; -	struct Scsi_Host *host = rts51x_to_host(chip); - -	for (;;) { -		if (wait_for_completion_interruptible(&chip->usb->cmnd_ready)) -			break; - -		if (test_bit(FLIDX_DISCONNECTING, &chip->usb->dflags)) { -			RTS51X_DEBUGP("-- exiting from rts51x-control\n"); -			break; -		} - -		/* lock the device pointers */ -		mutex_lock(&(chip->usb->dev_mutex)); - -		/* lock access to the state */ -		scsi_lock(host); - -		/* When we are called with no command pending, we're done */ -		if (chip->srb == NULL) { -			scsi_unlock(host); -			mutex_unlock(&chip->usb->dev_mutex); -			RTS51X_DEBUGP("-- exiting from control thread\n"); -			break; -		} - -		/* has the command timed out *already* ? */ -		if (test_bit(FLIDX_TIMED_OUT, &chip->usb->dflags)) { -			chip->srb->result = DID_ABORT << 16; -			goto SkipForAbort; -		} - -		scsi_unlock(host); - -		/* reject the command if the direction indicator -		 * is UNKNOWN -		 */ -		if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) { -			RTS51X_DEBUGP("UNKNOWN data direction\n"); -			chip->srb->result = DID_ERROR << 16; -		} - -		/* reject if target != 0 or if LUN is higher than -		 * the maximum known LUN -		 */ -		else if (chip->srb->device->id) { -			RTS51X_DEBUGP("Bad target number (%d:%d)\n", -				       chip->srb->device->id, -				       chip->srb->device->lun); -			chip->srb->result = DID_BAD_TARGET << 16; -		} - -		else if (chip->srb->device->lun > chip->max_lun) { -			RTS51X_DEBUGP("Bad LUN (%d:%d)\n", -				       chip->srb->device->id, -				       chip->srb->device->lun); -			chip->srb->result = DID_BAD_TARGET << 16; -		} - -		/* we've got a command, let's do it! */ -		else { -			RTS51X_DEBUG(rts51x_scsi_show_command(chip->srb)); -			rts51x_invoke_transport(chip->srb, chip); -		} - -		/* lock access to the state */ -		scsi_lock(host); - -		/* indicate that the command is done */ -		if (chip->srb->result != DID_ABORT << 16) -			chip->srb->scsi_done(chip->srb); -		else -SkipForAbort : -			RTS51X_DEBUGP("scsi command aborted\n"); - -		/* If an abort request was received we need to signal that -		 * the abort has finished.  The proper test for this is -		 * the TIMED_OUT flag, not srb->result == DID_ABORT, because -		 * the timeout might have occurred after the command had -		 * already completed with a different result code. */ -		if (test_bit(FLIDX_TIMED_OUT, &chip->usb->dflags)) { -			complete(&(chip->usb->notify)); - -			/* Allow USB transfers to resume */ -			clear_bit(FLIDX_ABORTING, &chip->usb->dflags); -			clear_bit(FLIDX_TIMED_OUT, &chip->usb->dflags); -		} - -		/* finished working on this command */ -		chip->srb = NULL; -		scsi_unlock(host); - -		/* unlock the device pointers */ -		mutex_unlock(&chip->usb->dev_mutex); -	}			/* for (;;) */ - -	complete(&chip->usb->control_exit); - -	/* Wait until we are told to stop */ -/*	for (;;) { -		set_current_state(TASK_INTERRUPTIBLE); -		if (kthread_should_stop()) -			break; -		schedule(); -	} -	__set_current_state(TASK_RUNNING);*/ -	return 0; -} - -static int rts51x_polling_thread(void *__chip) -{ -	struct rts51x_chip *chip = (struct rts51x_chip *)__chip; - -	for (;;) { -		wait_timeout(POLLING_INTERVAL); - -		/* if the device has disconnected, we are free to exit */ -		if (test_bit(FLIDX_DISCONNECTING, &chip->usb->dflags)) { -			RTS51X_DEBUGP("-- exiting from rts51x-polling\n"); -			break; -		} - -		/* if the device has disconnected, we are free to exit */ -		/* if (kthread_should_stop()) { -			printk(KERN_INFO "Stop polling thread!\n"); -			break; -		} */ - -#ifdef CONFIG_PM -		if (RTS51X_CHK_STAT(chip, STAT_SS) || -		    RTS51X_CHK_STAT(chip, STAT_SS_PRE) || -		    RTS51X_CHK_STAT(chip, STAT_SUSPEND)) { -			continue; -		} - -		if (ss_en) { -			if (RTS51X_CHK_STAT(chip, STAT_IDLE)) { -				if (chip->ss_counter < -				    (ss_delay * 1000 / POLLING_INTERVAL)) { -					chip->ss_counter++; -				} else { -					/* Prepare SS state */ -					RTS51X_SET_STAT(chip, STAT_SS_PRE); -					rts51x_try_to_enter_ss(chip); -					continue; -				} -			} else { -				chip->ss_counter = 0; -			} -		} -#endif - -		rts51x_mspro_polling_format_status(chip); - -		/* lock the device pointers */ -		mutex_lock(&(chip->usb->dev_mutex)); - -		rts51x_polling_func(chip); - -		/* unlock the device pointers */ -		mutex_unlock(&chip->usb->dev_mutex); -	}			/* for (;;) */ - -	complete(&chip->usb->polling_exit); - -	/* Wait until we are told to stop */ -	/* for (;;) { -		set_current_state(TASK_INTERRUPTIBLE); -		if (kthread_should_stop()) -		break; -		schedule(); -		} -	__set_current_state(TASK_RUNNING); */ -	return 0; -} - -/* Associate our private data with the USB device */ -static int associate_dev(struct rts51x_chip *chip, struct usb_interface *intf) -{ -	struct rts51x_usb *rts51x = chip->usb; -#ifdef SUPPORT_FILE_OP -	int retval; -#endif - -	/* Fill in the device-related fields */ -	rts51x->pusb_dev = interface_to_usbdev(intf); -	rts51x->pusb_intf = intf; -	rts51x->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; -	RTS51X_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n", -		       le16_to_cpu(rts51x->pusb_dev->descriptor.idVendor), -		       le16_to_cpu(rts51x->pusb_dev->descriptor.idProduct), -		       le16_to_cpu(rts51x->pusb_dev->descriptor.bcdDevice)); -	RTS51X_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n", -		       intf->cur_altsetting->desc.bInterfaceSubClass, -		       intf->cur_altsetting->desc.bInterfaceProtocol); - -	/* Store our private data in the interface */ -	usb_set_intfdata(intf, chip); - -#ifdef SUPPORT_FILE_OP -	/* we can register the device now, as it is ready */ -	retval = usb_register_dev(intf, &rts51x_class); -	if (retval) { -		/* something prevented us from registering this driver */ -		RTS51X_DEBUGP("Not able to get a minor for this device."); -		usb_set_intfdata(intf, NULL); -		return -ENOMEM; -	} -#endif - -	/* Allocate the device-related DMA-mapped buffers */ -	rts51x->cr = usb_buffer_alloc(rts51x->pusb_dev, sizeof(*rts51x->cr), -				      GFP_KERNEL, &rts51x->cr_dma); -	if (!rts51x->cr) { -		RTS51X_DEBUGP("usb_ctrlrequest allocation failed\n"); -		usb_set_intfdata(intf, NULL); -		return -ENOMEM; -	} - -	rts51x->iobuf = usb_buffer_alloc(rts51x->pusb_dev, RTS51X_IOBUF_SIZE, -					 GFP_KERNEL, &rts51x->iobuf_dma); -	if (!rts51x->iobuf) { -		RTS51X_DEBUGP("I/O buffer allocation failed\n"); -		usb_set_intfdata(intf, NULL); -		return -ENOMEM; -	} -	return 0; -} - -static void rts51x_init_options(struct rts51x_chip *chip) -{ -	struct rts51x_option *option = &(chip->option); - -	option->rts51x_mspro_formatter_enable = 1; - -	option->fpga_sd_sdr104_clk = CLK_100; -	option->fpga_sd_sdr50_clk = CLK_100; -	option->fpga_sd_ddr50_clk = CLK_100; -	option->fpga_sd_hs_clk = CLK_100; -	option->fpga_mmc_52m_clk = CLK_80; -	option->fpga_ms_hg_clk = CLK_80; -	option->fpga_ms_4bit_clk = CLK_80; - -	option->asic_sd_sdr104_clk = 98; -	option->asic_sd_sdr50_clk = 98; -	option->asic_sd_ddr50_clk = 98; -	option->asic_sd_hs_clk = 97; -	option->asic_mmc_52m_clk = 95; -	option->asic_ms_hg_clk = 116; -	option->asic_ms_4bit_clk = 77; - -	option->sd_ddr_tx_phase = 0; -	option->mmc_ddr_tx_phase = 1; - -	option->sd_speed_prior = 0; -	option->sd_ctl = -	    SD_PUSH_POINT_AUTO | SD_SAMPLE_POINT_AUTO | SUPPORT_UHS50_MMC44; - -	option->ss_en = ss_en; -	option->ss_delay = ss_delay; - -	option->auto_delink_en = auto_delink_en; - -	option->FT2_fast_mode = 0; -	option->pwr_delay = 800; -	option->rts51x_xd_rw_step = 0; -	option->D3318_off_delay = 50; -	option->delink_delay = 100; -	option->rts5129_D3318_off_enable = 0; -	option->sd20_pad_drive = 0; -	option->reset_or_rw_fail_set_pad_drive = 1; -	option->debounce_num = 2; -	option->led_toggle_interval = 6; -	option->rts51x_xd_rwn_step = 0; -	option->sd_send_status_en = 0; -	option->sdr50_tx_phase = 0x01; -	option->sdr50_rx_phase = 0x05; -	option->ddr50_tx_phase = 0x09; -	option->ddr50_rx_phase = 0x06; -	option->sdr50_phase_sel = 0; -	option->sd30_pad_drive = 1; -	option->ms_errreg_fix = 0; -	option->reset_mmc_first = 0; -	option->speed_mmc = 1; -	option->led_always_on = 0; -} - -/* Get the pipe settings */ -static int get_pipes(struct rts51x_chip *chip) -{ -	struct rts51x_usb *rts51x = chip->usb; -	struct usb_host_interface *altsetting = -	    rts51x->pusb_intf->cur_altsetting; -	int i; -	struct usb_endpoint_descriptor *ep; -	struct usb_endpoint_descriptor *ep_in = NULL; -	struct usb_endpoint_descriptor *ep_out = NULL; -	struct usb_endpoint_descriptor *ep_int = NULL; - -	/* -	 * Find the first endpoint of each type we need. -	 * We are expecting a minimum of 2 endpoints - in and out (bulk). -	 * An optional interrupt-in is OK (necessary for CBI protocol). -	 * We will ignore any others. -	 */ -	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { -		ep = &altsetting->endpoint[i].desc; - -		if (usb_endpoint_xfer_bulk(ep)) { -			if (usb_endpoint_dir_in(ep)) { -				if (!ep_in) -					ep_in = ep; -			} else { -				if (!ep_out) -					ep_out = ep; -			} -		} - -		else if (usb_endpoint_is_int_in(ep)) { -			if (!ep_int) -				ep_int = ep; -		} -	} - -	if (!ep_in || !ep_out) { -		RTS51X_DEBUGP("Endpoint sanity check failed!" -					"Rejecting dev.\n"); -		return -EIO; -	} - -	/* Calculate and store the pipe values */ -	rts51x->send_ctrl_pipe = usb_sndctrlpipe(rts51x->pusb_dev, 0); -	rts51x->recv_ctrl_pipe = usb_rcvctrlpipe(rts51x->pusb_dev, 0); -	rts51x->send_bulk_pipe = usb_sndbulkpipe(rts51x->pusb_dev, -						 usb_endpoint_num(ep_out)); -	rts51x->recv_bulk_pipe = usb_rcvbulkpipe(rts51x->pusb_dev, -						 usb_endpoint_num(ep_in)); -	if (ep_int) { -		rts51x->recv_intr_pipe = usb_rcvintpipe(rts51x->pusb_dev, -							usb_endpoint_num -							(ep_int)); -		rts51x->ep_bInterval = ep_int->bInterval; -	} -	return 0; -} - -/* Initialize all the dynamic resources we need */ -static int rts51x_acquire_resources(struct rts51x_chip *chip) -{ -	struct rts51x_usb *rts51x = chip->usb; -	int retval; - -	rts51x->current_urb = usb_alloc_urb(0, GFP_KERNEL); -	if (!rts51x->current_urb) { -		RTS51X_DEBUGP("URB allocation failed\n"); -		return -ENOMEM; -	} - -	rts51x->intr_urb = usb_alloc_urb(0, GFP_KERNEL); -	if (!rts51x->intr_urb) { -		RTS51X_DEBUGP("URB allocation failed\n"); -		return -ENOMEM; -	} - -	chip->cmd_buf = chip->rsp_buf = rts51x->iobuf; - -	rts51x_init_options(chip); - -	/* Init rts51xx device */ -	retval = rts51x_init_chip(chip); -	if (retval != STATUS_SUCCESS) -		return -EIO; - -	return 0; -} - -/* Release all our dynamic resources */ -static void rts51x_release_resources(struct rts51x_chip *chip) -{ -	RTS51X_DEBUGP("-- %s\n", __func__); - -	/* Tell the control thread to exit.  The SCSI host must -	 * already have been removed and the DISCONNECTING flag set -	 * so that we won't accept any more commands. -	 */ -	RTS51X_DEBUGP("-- sending exit command to thread\n"); -	complete(&chip->usb->cmnd_ready); -	if (chip->usb->ctl_thread) -		wait_for_completion(&chip->usb->control_exit); -		/* kthread_stop(chip->usb->ctl_thread); */ -	if (chip->usb->polling_thread) -		wait_for_completion(&chip->usb->polling_exit); - -	/* if (chip->usb->polling_thread) -		kthread_stop(chip->usb->polling_thread); */ - -	wait_timeout(200); - -	/* Release rts51xx device here */ -	rts51x_release_chip(chip); - -	usb_free_urb(chip->usb->current_urb); -	usb_free_urb(chip->usb->intr_urb); -} - -/* Dissociate from the USB device */ -static void dissociate_dev(struct rts51x_chip *chip) -{ -	struct rts51x_usb *rts51x = chip->usb; - -	RTS51X_DEBUGP("-- %s\n", __func__); - -	/* Free the device-related DMA-mapped buffers */ -	if (rts51x->cr) -		usb_buffer_free(rts51x->pusb_dev, sizeof(*rts51x->cr), -				rts51x->cr, rts51x->cr_dma); -	if (rts51x->iobuf) -		usb_buffer_free(rts51x->pusb_dev, RTS51X_IOBUF_SIZE, -				rts51x->iobuf, rts51x->iobuf_dma); - -	/* Remove our private data from the interface */ -	usb_set_intfdata(rts51x->pusb_intf, NULL); - -#ifdef SUPPORT_FILE_OP -	/* give back our minor */ -	usb_deregister_dev(rts51x->pusb_intf, &rts51x_class); -#endif - -	kfree(rts51x); -	chip->usb = NULL; -} - -/* First stage of disconnect processing: stop SCSI scanning, - * remove the host, and stop accepting new commands - */ -static void quiesce_and_remove_host(struct rts51x_chip *chip) -{ -	struct rts51x_usb *rts51x = chip->usb; -	struct Scsi_Host *host = rts51x_to_host(chip); - -	/* If the device is really gone, cut short reset delays */ -	if (rts51x->pusb_dev->state == USB_STATE_NOTATTACHED) -		set_bit(FLIDX_DISCONNECTING, &rts51x->dflags); - -	/* Removing the host will perform an orderly shutdown: caches -	 * synchronized, disks spun down, etc. -	 */ -	scsi_remove_host(host); - -	/* Prevent any new commands from being accepted and cut short -	 * reset delays. -	 */ -	scsi_lock(host); -	set_bit(FLIDX_DISCONNECTING, &rts51x->dflags); -	scsi_unlock(host); -} - -/* Second stage of disconnect processing: deallocate all resources */ -static void release_everything(struct rts51x_chip *chip) -{ -	rts51x_release_resources(chip); -	dissociate_dev(chip); - -	/* Drop our reference to the host; the SCSI core will free it -	 * (and "chip" along with it) when the refcount becomes 0. */ -	scsi_host_put(rts51x_to_host(chip)); -} - -static int rts51x_probe(struct usb_interface *intf, -			const struct usb_device_id *id) -{ -	struct Scsi_Host *host; -	struct rts51x_chip *chip; -	struct rts51x_usb *rts51x; -	int result; -	struct task_struct *th; - -	RTS51X_DEBUGP("%s detected\n", RTS51X_NAME); - -	rts51x = kzalloc(sizeof(struct rts51x_usb), GFP_KERNEL); -	if (!rts51x) { -		printk(KERN_WARNING RTS51X_TIP -		       "Unable to allocate rts51x_usb\n"); -		return -ENOMEM; -	} - -	/* -	 * Ask the SCSI layer to allocate a host structure, with extra -	 * space at the end for our private us_data structure. -	 */ -	host = scsi_host_alloc(&rts51x_host_template, sizeof(*chip)); -	if (!host) { -		printk(KERN_WARNING RTS51X_TIP -		       "Unable to allocate the scsi host\n"); -		kfree(rts51x); -		return -ENOMEM; -	} - -	/* -	 * Allow 16-byte CDBs and thus > 2TB -	 */ -	host->max_cmd_len = 16; -	chip = host_to_rts51x(host); -	memset(chip, 0, sizeof(struct rts51x_chip)); - -	chip->vendor_id = id->idVendor; -	chip->product_id = id->idProduct; - -	mutex_init(&(rts51x->dev_mutex)); -	init_completion(&rts51x->cmnd_ready); -	init_completion(&rts51x->control_exit); -	init_completion(&rts51x->polling_exit); -	init_completion(&(rts51x->notify)); - -	chip->usb = rts51x; - -	/* Associate the us_data structure with the USB device */ -	result = associate_dev(chip, intf); -	if (result) -		goto BadDevice; - -	/* Find the endpoints and calculate pipe values */ -	result = get_pipes(chip); -	if (result) -		goto BadDevice; - -	/* Acquire all the other resources and add the host */ -	result = rts51x_acquire_resources(chip); -	if (result) -		goto BadDevice; - -	/* Start up our control thread */ -	th = kthread_run(rts51x_control_thread, chip, RTS51X_CTL_THREAD); -	if (IS_ERR(th)) { -		printk(KERN_WARNING RTS51X_TIP -		       "Unable to start control thread\n"); -		result = PTR_ERR(th); -		goto BadDevice; -	} -	rts51x->ctl_thread = th; - -	result = scsi_add_host(rts51x_to_host(chip), &rts51x->pusb_intf->dev); -	if (result) { -		printk(KERN_WARNING RTS51X_TIP "Unable to add the scsi host\n"); -		goto BadDevice; -	} -	scsi_scan_host(rts51x_to_host(chip)); - -	/* Start up our polling thread */ -	th = kthread_run(rts51x_polling_thread, chip, RTS51X_POLLING_THREAD); -	if (IS_ERR(th)) { -		printk(KERN_WARNING RTS51X_TIP -		       "Unable to start polling thread\n"); -		result = PTR_ERR(th); -		goto BadDevice; -	} -	rts51x->polling_thread = th; - -#ifdef CONFIG_PM -	if (ss_en) { -		rts51x->pusb_intf->needs_remote_wakeup = needs_remote_wakeup; -		SET_PM_USAGE_CNT(chip, 1); -		RTS51X_DEBUGP("pm_usage_cnt = %d\n", GET_PM_USAGE_CNT(chip)); -	} -#endif - -	return 0; - -	/* We come here if there are any problems */ -BadDevice: -	RTS51X_DEBUGP("rts51x_probe() failed\n"); -	release_everything(chip); -	return result; -} - -static void rts51x_disconnect(struct usb_interface *intf) -{ -	struct rts51x_chip *chip = (struct rts51x_chip *)usb_get_intfdata(intf); - -	RTS51X_DEBUGP("rts51x_disconnect() called\n"); -	quiesce_and_remove_host(chip); -	release_everything(chip); -} - -/*********************************************************************** - * Initialization and registration - ***********************************************************************/ - -struct usb_device_id rts5139_usb_ids[] = { -	{USB_DEVICE(0x0BDA, 0x0139)}, -	{USB_DEVICE(0x0BDA, 0x0129)}, -	{}			/* Terminating entry */ -}; -EXPORT_SYMBOL_GPL(rts5139_usb_ids); - -MODULE_DEVICE_TABLE(usb, rts5139_usb_ids); - -struct usb_driver rts51x_driver = { -	.name = RTS51X_NAME, -	.probe = rts51x_probe, -	.disconnect = rts51x_disconnect, -	.suspend = rts51x_suspend, -	.resume = rts51x_resume, -	.reset_resume = rts51x_reset_resume, -	.pre_reset = rts51x_pre_reset, -	.post_reset = rts51x_post_reset, -	.id_table = rts5139_usb_ids, -	.soft_unbind = 1, -}; - -module_usb_driver(rts51x_driver);  | 
