1 #include <linux/libata.h> 2 #include <linux/cdrom.h> 3 #include <linux/pm_runtime.h> 4 #include <linux/module.h> 5 #include <scsi/scsi_device.h> 6 7 #include "libata.h" 8 9 static int zpodd_poweroff_delay = 30; /* 30 seconds for power off delay */ 10 module_param(zpodd_poweroff_delay, int, 0644); 11 MODULE_PARM_DESC(zpodd_poweroff_delay, "Poweroff delay for ZPODD in seconds"); 12 13 enum odd_mech_type { 14 ODD_MECH_TYPE_SLOT, 15 ODD_MECH_TYPE_DRAWER, 16 ODD_MECH_TYPE_UNSUPPORTED, 17 }; 18 19 struct zpodd { 20 enum odd_mech_type mech_type; /* init during probe, RO afterwards */ 21 struct ata_device *dev; 22 23 /* The following fields are synchronized by PM core. */ 24 bool from_notify; /* resumed as a result of 25 * acpi wake notification */ 26 bool zp_ready; /* ZP ready state */ 27 unsigned long last_ready; /* last ZP ready timestamp */ 28 bool zp_sampled; /* ZP ready state sampled */ 29 bool powered_off; /* ODD is powered off 30 * during suspend */ 31 }; 32 33 static int eject_tray(struct ata_device *dev) 34 { 35 struct ata_taskfile tf; 36 const char cdb[] = { GPCMD_START_STOP_UNIT, 37 0, 0, 0, 38 0x02, /* LoEj */ 39 0, 0, 0, 0, 0, 0, 0, 40 }; 41 42 ata_tf_init(dev, &tf); 43 tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; 44 tf.command = ATA_CMD_PACKET; 45 tf.protocol = ATAPI_PROT_NODATA; 46 47 return ata_exec_internal(dev, &tf, cdb, DMA_NONE, NULL, 0, 0); 48 } 49 50 /* Per the spec, only slot type and drawer type ODD can be supported */ 51 static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev) 52 { 53 char buf[16]; 54 unsigned int ret; 55 struct rm_feature_desc *desc = (void *)(buf + 8); 56 struct ata_taskfile tf; 57 char cdb[] = { GPCMD_GET_CONFIGURATION, 58 2, /* only 1 feature descriptor requested */ 59 0, 3, /* 3, removable medium feature */ 60 0, 0, 0,/* reserved */ 61 0, sizeof(buf), 62 0, 0, 0, 63 }; 64 65 ata_tf_init(dev, &tf); 66 tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; 67 tf.command = ATA_CMD_PACKET; 68 tf.protocol = ATAPI_PROT_PIO; 69 tf.lbam = sizeof(buf); 70 71 ret = ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE, 72 buf, sizeof(buf), 0); 73 if (ret) 74 return ODD_MECH_TYPE_UNSUPPORTED; 75 76 if (be16_to_cpu(desc->feature_code) != 3) 77 return ODD_MECH_TYPE_UNSUPPORTED; 78 79 if (desc->mech_type == 0 && desc->load == 0 && desc->eject == 1) 80 return ODD_MECH_TYPE_SLOT; 81 else if (desc->mech_type == 1 && desc->load == 0 && desc->eject == 1) 82 return ODD_MECH_TYPE_DRAWER; 83 else 84 return ODD_MECH_TYPE_UNSUPPORTED; 85 } 86 87 static bool odd_can_poweroff(struct ata_device *ata_dev) 88 { 89 acpi_handle handle; 90 acpi_status status; 91 struct acpi_device *acpi_dev; 92 93 handle = ata_dev_acpi_handle(ata_dev); 94 if (!handle) 95 return false; 96 97 status = acpi_bus_get_device(handle, &acpi_dev); 98 if (ACPI_FAILURE(status)) 99 return false; 100 101 return acpi_device_can_poweroff(acpi_dev); 102 } 103 104 /* Test if ODD is zero power ready by sense code */ 105 static bool zpready(struct ata_device *dev) 106 { 107 u8 sense_key, *sense_buf; 108 unsigned int ret, asc, ascq, add_len; 109 struct zpodd *zpodd = dev->zpodd; 110 111 ret = atapi_eh_tur(dev, &sense_key); 112 113 if (!ret || sense_key != NOT_READY) 114 return false; 115 116 sense_buf = dev->link->ap->sector_buf; 117 ret = atapi_eh_request_sense(dev, sense_buf, sense_key); 118 if (ret) 119 return false; 120 121 /* sense valid */ 122 if ((sense_buf[0] & 0x7f) != 0x70) 123 return false; 124 125 add_len = sense_buf[7]; 126 /* has asc and ascq */ 127 if (add_len < 6) 128 return false; 129 130 asc = sense_buf[12]; 131 ascq = sense_buf[13]; 132 133 if (zpodd->mech_type == ODD_MECH_TYPE_SLOT) 134 /* no media inside */ 135 return asc == 0x3a; 136 else 137 /* no media inside and door closed */ 138 return asc == 0x3a && ascq == 0x01; 139 } 140 141 /* 142 * Update the zpodd->zp_ready field. This field will only be set 143 * if the ODD has stayed in ZP ready state for zpodd_poweroff_delay 144 * time, and will be used to decide if power off is allowed. If it 145 * is set, it will be cleared during resume from powered off state. 146 */ 147 void zpodd_on_suspend(struct ata_device *dev) 148 { 149 struct zpodd *zpodd = dev->zpodd; 150 unsigned long expires; 151 152 if (!zpready(dev)) { 153 zpodd->zp_sampled = false; 154 zpodd->zp_ready = false; 155 return; 156 } 157 158 if (!zpodd->zp_sampled) { 159 zpodd->zp_sampled = true; 160 zpodd->last_ready = jiffies; 161 return; 162 } 163 164 expires = zpodd->last_ready + 165 msecs_to_jiffies(zpodd_poweroff_delay * 1000); 166 if (time_before(jiffies, expires)) 167 return; 168 169 zpodd->zp_ready = true; 170 } 171 172 bool zpodd_zpready(struct ata_device *dev) 173 { 174 struct zpodd *zpodd = dev->zpodd; 175 return zpodd->zp_ready; 176 } 177 178 /* 179 * Enable runtime wake capability through ACPI and set the powered_off flag, 180 * this flag will be used during resume to decide what operations are needed 181 * to take. 182 * 183 * Also, media poll needs to be silenced, so that it doesn't bring the ODD 184 * back to full power state every few seconds. 185 */ 186 void zpodd_enable_run_wake(struct ata_device *dev) 187 { 188 struct zpodd *zpodd = dev->zpodd; 189 190 sdev_disable_disk_events(dev->sdev); 191 192 zpodd->powered_off = true; 193 device_set_run_wake(&dev->sdev->sdev_gendev, true); 194 acpi_pm_device_run_wake(&dev->sdev->sdev_gendev, true); 195 } 196 197 /* Disable runtime wake capability if it is enabled */ 198 void zpodd_disable_run_wake(struct ata_device *dev) 199 { 200 struct zpodd *zpodd = dev->zpodd; 201 202 if (zpodd->powered_off) { 203 acpi_pm_device_run_wake(&dev->sdev->sdev_gendev, false); 204 device_set_run_wake(&dev->sdev->sdev_gendev, false); 205 } 206 } 207 208 /* 209 * Post power on processing after the ODD has been recovered. If the 210 * ODD wasn't powered off during suspend, it doesn't do anything. 211 * 212 * For drawer type ODD, if it is powered on due to user pressed the 213 * eject button, the tray needs to be ejected. This can only be done 214 * after the ODD has been recovered, i.e. link is initialized and 215 * device is able to process NON_DATA PIO command, as eject needs to 216 * send command for the ODD to process. 217 * 218 * The from_notify flag set in wake notification handler function 219 * zpodd_wake_dev represents if power on is due to user's action. 220 * 221 * For both types of ODD, several fields need to be reset. 222 */ 223 void zpodd_post_poweron(struct ata_device *dev) 224 { 225 struct zpodd *zpodd = dev->zpodd; 226 227 if (!zpodd->powered_off) 228 return; 229 230 zpodd->powered_off = false; 231 232 if (zpodd->from_notify) { 233 zpodd->from_notify = false; 234 if (zpodd->mech_type == ODD_MECH_TYPE_DRAWER) 235 eject_tray(dev); 236 } 237 238 zpodd->zp_sampled = false; 239 zpodd->zp_ready = false; 240 241 sdev_enable_disk_events(dev->sdev); 242 } 243 244 static void zpodd_wake_dev(acpi_handle handle, u32 event, void *context) 245 { 246 struct ata_device *ata_dev = context; 247 struct zpodd *zpodd = ata_dev->zpodd; 248 struct device *dev = &ata_dev->sdev->sdev_gendev; 249 250 if (event == ACPI_NOTIFY_DEVICE_WAKE && pm_runtime_suspended(dev)) { 251 zpodd->from_notify = true; 252 pm_runtime_resume(dev); 253 } 254 } 255 256 static void ata_acpi_add_pm_notifier(struct ata_device *dev) 257 { 258 acpi_handle handle = ata_dev_acpi_handle(dev); 259 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, 260 zpodd_wake_dev, dev); 261 } 262 263 static void ata_acpi_remove_pm_notifier(struct ata_device *dev) 264 { 265 acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->sdev->sdev_gendev); 266 acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, zpodd_wake_dev); 267 } 268 269 void zpodd_init(struct ata_device *dev) 270 { 271 enum odd_mech_type mech_type; 272 struct zpodd *zpodd; 273 274 if (dev->zpodd) 275 return; 276 277 if (!odd_can_poweroff(dev)) 278 return; 279 280 mech_type = zpodd_get_mech_type(dev); 281 if (mech_type == ODD_MECH_TYPE_UNSUPPORTED) 282 return; 283 284 zpodd = kzalloc(sizeof(struct zpodd), GFP_KERNEL); 285 if (!zpodd) 286 return; 287 288 zpodd->mech_type = mech_type; 289 290 ata_acpi_add_pm_notifier(dev); 291 zpodd->dev = dev; 292 dev->zpodd = zpodd; 293 } 294 295 void zpodd_exit(struct ata_device *dev) 296 { 297 ata_acpi_remove_pm_notifier(dev); 298 kfree(dev->zpodd); 299 dev->zpodd = NULL; 300 } 301