Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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