Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Unified Diff: drivers/usb/storage/realtek_cr.c

Issue 2064009: Version 1.02 of the Realtek USB card reader driver fixes the lsusb hang. (Closed) Base URL: ssh://git@chromiumos-git/kernel.git
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: drivers/usb/storage/realtek_cr.c
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index 6873ecec391e3808e7eac05ec1b869c29eb9d7a7..c678b91d2351c14e190328d35e8c58e28b7e9154 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -44,12 +44,13 @@
MODULE_DESCRIPTION("Driver for Realtek USB Card Reader");
MODULE_AUTHOR("wwang <wei_wang@realsil.com.cn>");
MODULE_LICENSE("GPL");
+MODULE_VERSION("1.02");
static int ss_en = 1;
module_param(ss_en, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ss_en, "enable selective suspend");
-static int ss_delay = 20;
+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");
@@ -61,7 +62,7 @@ static int auto_delink_en = 1;
module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
-enum CHIP_STAT {STAT_INIT, STAT_IDLE, STAT_RUN, STAT_SS_PRE, STAT_SS};
+enum CHIP_STAT {STAT_INIT, STAT_IDLE, STAT_RUN, STAT_SS_PRE, STAT_SS, STAT_SUSPEND};
struct rts51x_status {
u16 vid;
@@ -90,6 +91,8 @@ struct rts51x_chip {
int idle_counter;
enum CHIP_STAT chip_stat;
+ int resume_from_scsi;
+
struct rts51x_status *status;
int status_len;
u8 lun_ready;
@@ -422,6 +425,8 @@ static int rts51x_check_status(struct us_data *us, u8 lun)
return -EIO;
}
+ US_DEBUGP("chip->status_len = %d\n", chip->status_len);
+
chip->status[lun].vid = ((u16)buf[0] << 8) | buf[1];
chip->status[lun].pid = ((u16)buf[2] << 8) | buf[3];
chip->status[lun].cur_lun = buf[4];
@@ -655,8 +660,13 @@ static int config_autodelink_before_power_down(struct us_data *us)
static void rts51x_polling_func(struct us_data *us)
{
struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+
+ /* lock the device pointers */
+ mutex_lock(&(us->dev_mutex));
if (RTS51X_CHK_STAT(chip, STAT_SS) || RTS51X_CHK_STAT(chip, STAT_SS_PRE)) {
+ /* unlock the device pointers */
+ mutex_unlock(&(us->dev_mutex));
return;
}
@@ -668,6 +678,9 @@ static void rts51x_polling_func(struct us_data *us)
} else {
US_DEBUGP("Ready to enter SS state\n");
RTS51X_SET_STAT(chip, STAT_SS_PRE); // Prepare SS state
+
+ /* unlock the device pointers */
+ mutex_unlock(&(us->dev_mutex));
usb_autopm_enable(us->pusb_intf);
return;
}
@@ -686,16 +699,8 @@ static void rts51x_polling_func(struct us_data *us)
}
}
- switch (RTS51X_GET_STAT(chip)) {
- case STAT_RUN:
- break;
-
- case STAT_IDLE:
- break;
-
- default:
- break;
- }
+ /* unlock the device pointers */
+ mutex_unlock(&(us->dev_mutex));
}
static int rts51x_polling_thread(void * __us)
@@ -714,13 +719,8 @@ static int rts51x_polling_thread(void * __us)
break;
}
- /* lock the device pointers */
- mutex_lock(&(us->dev_mutex));
-
rts51x_polling_func(us);
-
- /* unlock the device pointers */
- mutex_unlock(&(us->dev_mutex));
+
} /* for (;;) */
__set_current_state(TASK_RUNNING);
@@ -728,31 +728,58 @@ static int rts51x_polling_thread(void * __us)
}
#ifdef CONFIG_PM
-static void rts51x_handle_pm(struct us_data *us, int pwr_state)
+int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)
{
+ struct us_data *us = usb_get_intfdata(iface);
struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+
+ US_DEBUGP("%s, message.event = 0x%x\n", __func__, message.event);
+
+ /* Wait until no command is running */
+ mutex_lock(&us->dev_mutex);
- US_DEBUGP("Handle pm state: %s\n", pwr_state ? "resume" : "suspend");
+ if (message.event == PM_EVENT_AUTO_SUSPEND) {
+ US_DEBUGP("Enter SS state");
+ chip->resume_from_scsi = 0;
+ RTS51X_SET_STAT(chip, STAT_SS);
+ } else {
+ US_DEBUGP("Enter SUSPEND state");
+ RTS51X_SET_STAT(chip, STAT_SUSPEND);
+ }
+ (void)config_autodelink_before_power_down(us);
+
+ /* When runtime PM is working, we'll set a flag to indicate
+ * whether we should autoresume when a SCSI request arrives. */
+
+ mutex_unlock(&us->dev_mutex);
+
+ return 0;
+}
+
+int realtek_cr_resume(struct usb_interface *iface)
+{
+ struct us_data *us = usb_get_intfdata(iface);
+ struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+
+ US_DEBUGP("%s\n", __func__);
+
+ if (!RTS51X_CHK_STAT(chip, STAT_SS) || !chip->resume_from_scsi) {
+ mutex_lock(&us->dev_mutex);
- if (pwr_state == US_RESUME) {
if (GET_PM_USAGE_CNT(us) <= 0) {
// Remote wake up, increase pm_usage_cnt
US_DEBUGP("Incr pm_usage_cnt\n");
SET_PM_USAGE_CNT(us, 1);
- RTS51X_SET_STAT(chip, STAT_RUN);
}
-
+
(void)config_autodelink_after_power_on(us);
- } else {
- if (RTS51X_CHK_STAT(chip, STAT_SS_PRE)) {
- US_DEBUGP("Enter SS state");
- RTS51X_SET_STAT(chip, STAT_SS);
- }
-
- (void)config_autodelink_before_power_down(us);
+
+ RTS51X_SET_STAT(chip, STAT_RUN);
+
+ mutex_unlock(&us->dev_mutex);
}
- US_DEBUGP("pm_usage_cnt = %d\n", GET_PM_USAGE_CNT(us));
+ return 0;
}
#endif
@@ -786,10 +813,6 @@ static int init_realtek_cr(struct us_data *us)
us->extra = chip;
us->extra_destructor = realtek_cr_destructor;
-#ifdef CONFIG_PM
- us->suspend_resume_hook = rts51x_handle_pm;
-#endif
-
us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
US_DEBUGP("chip->max_lun = %d\n", chip->max_lun);
@@ -817,6 +840,8 @@ static int init_realtek_cr(struct us_data *us)
}
}
+ US_DEBUGP("chip->flag = 0x%x\n", chip->flag);
+
(void)config_autodelink_after_power_on(us);
#ifdef CONFIG_PM
@@ -895,10 +920,11 @@ static int realtek_cr_transport(struct scsi_cmnd *srb, struct us_data *us)
if (RTS51X_CHK_STAT(chip, STAT_SS)) {
// Wake up device
US_DEBUGP("Try to wake up device\n");
- mutex_unlock(&(us->dev_mutex));
+ chip->resume_from_scsi = 1;
usb_autopm_disable(us->pusb_intf);
wait_timeout(3000);
- mutex_lock(&(us->dev_mutex));
+
+ (void)config_autodelink_after_power_on(us);
rts51x_reset_card(us, lun);
}
RTS51X_SET_STAT(chip, STAT_RUN);
@@ -950,8 +976,8 @@ static struct usb_driver realtek_cr_driver = {
.name = "ums-realtek",
.probe = realtek_cr_probe,
.disconnect = usb_stor_disconnect,
- .suspend = usb_stor_suspend,
- .resume = usb_stor_resume,
+ .suspend = realtek_cr_suspend,
+ .resume = realtek_cr_resume,
.reset_resume = usb_stor_reset_resume,
.pre_reset = usb_stor_pre_reset,
.post_reset = usb_stor_post_reset,
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698