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