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-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * SCSI Enclosure Services
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/enclosure.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <scsi/scsi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <scsi/scsi_cmnd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <scsi/scsi_dbg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <scsi/scsi_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <scsi/scsi_driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <scsi/scsi_transport_sas.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) struct ses_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	unsigned char *page1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	unsigned char *page1_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	unsigned char *page2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	unsigned char *page10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	short page1_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	short page1_num_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	short page2_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	short page10_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) struct ses_component {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	u64 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) static bool ses_page2_supported(struct enclosure_device *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct ses_device *ses_dev = edev->scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	return (ses_dev->page2 != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static int ses_probe(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	struct scsi_device *sdev = to_scsi_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	int err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	if (sdev->type != TYPE_ENCLOSURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	sdev_printk(KERN_NOTICE, sdev, "Attached Enclosure device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) #define SES_TIMEOUT (30 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) #define SES_RETRIES 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) static void init_device_slot_control(unsigned char *dest_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 				     struct enclosure_component *ecomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 				     unsigned char *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	memcpy(dest_desc, status, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	dest_desc[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	/* only clear byte 1 for ENCLOSURE_COMPONENT_DEVICE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	if (ecomp->type == ENCLOSURE_COMPONENT_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		dest_desc[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	dest_desc[2] &= 0xde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	dest_desc[3] &= 0x3c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static int ses_recv_diag(struct scsi_device *sdev, int page_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			 void *buf, int bufflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	unsigned char cmd[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		RECEIVE_DIAGNOSTIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		1,		/* Set PCV bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		page_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		bufflen >> 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		bufflen & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	unsigned char recv_page_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	unsigned int retries = SES_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	struct scsi_sense_hdr sshdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		ret = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 				       &sshdr, SES_TIMEOUT, 1, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	} while (ret > 0 && --retries && scsi_sense_valid(&sshdr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		 (sshdr.sense_key == NOT_READY ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		  (sshdr.sense_key == UNIT_ATTENTION && sshdr.asc == 0x29)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (unlikely(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	recv_page_code = ((unsigned char *)buf)[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	if (likely(recv_page_code == page_code))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	/* successful diagnostic but wrong page code.  This happens to some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	 * USB devices, just print a message and pretend there was an error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	sdev_printk(KERN_ERR, sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		    "Wrong diagnostic page; asked for %d got %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		    page_code, recv_page_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int ses_send_diag(struct scsi_device *sdev, int page_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			 void *buf, int bufflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	unsigned char cmd[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		SEND_DIAGNOSTIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		0x10,		/* Set PF bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		bufflen >> 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		bufflen & 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	struct scsi_sense_hdr sshdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	unsigned int retries = SES_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, buf, bufflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 					  &sshdr, SES_TIMEOUT, 1, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	} while (result > 0 && --retries && scsi_sense_valid(&sshdr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		 (sshdr.sense_key == NOT_READY ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		  (sshdr.sense_key == UNIT_ATTENTION && sshdr.asc == 0x29)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		sdev_printk(KERN_ERR, sdev, "SEND DIAGNOSTIC result: %8x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			    result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int ses_set_page2_descriptor(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 				      struct enclosure_component *ecomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 				      unsigned char *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	int i, j, count = 0, descriptor = ecomp->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	struct ses_device *ses_dev = edev->scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	unsigned char *type_ptr = ses_dev->page1_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	unsigned char *desc_ptr = ses_dev->page2 + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	/* Clear everything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	memset(desc_ptr, 0, ses_dev->page2_len - 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		for (j = 0; j < type_ptr[1]; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			desc_ptr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 			if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 			    type_ptr[0] != ENCLOSURE_COMPONENT_ARRAY_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			if (count++ == descriptor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 				memcpy(desc_ptr, desc, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 				/* set select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 				desc_ptr[0] |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 				/* clear reserved, just in case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 				desc_ptr[0] &= 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	return ses_send_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len);
^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) static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 				      struct enclosure_component *ecomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	int i, j, count = 0, descriptor = ecomp->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	struct ses_device *ses_dev = edev->scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	unsigned char *type_ptr = ses_dev->page1_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	unsigned char *desc_ptr = ses_dev->page2 + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	if (ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		for (j = 0; j < type_ptr[1]; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 			desc_ptr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			    type_ptr[0] != ENCLOSURE_COMPONENT_ARRAY_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 			if (count++ == descriptor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 				return desc_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* For device slot and array device slot elements, byte 3 bit 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  * is "fault sensed" while byte 3 bit 5 is "fault reqstd". As this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * code stands these bits are shifted 4 positions right so in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  * sysfs they will appear as bits 2 and 1 respectively. Strange. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static void ses_get_fault(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			  struct enclosure_component *ecomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	unsigned char *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	if (!ses_page2_supported(edev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		ecomp->fault = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	desc = ses_get_page2_descriptor(edev, ecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	if (desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		ecomp->fault = (desc[3] & 0x60) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int ses_set_fault(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 			  struct enclosure_component *ecomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 			 enum enclosure_component_setting val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	unsigned char desc[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	unsigned char *desc_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	if (!ses_page2_supported(edev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	desc_ptr = ses_get_page2_descriptor(edev, ecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	if (!desc_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	init_device_slot_control(desc, ecomp, desc_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	case ENCLOSURE_SETTING_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		desc[3] &= 0xdf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	case ENCLOSURE_SETTING_ENABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		desc[3] |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		/* SES doesn't do the SGPIO blink settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	return ses_set_page2_descriptor(edev, ecomp, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static void ses_get_status(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			   struct enclosure_component *ecomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	unsigned char *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	if (!ses_page2_supported(edev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		ecomp->status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	desc = ses_get_page2_descriptor(edev, ecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	if (desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		ecomp->status = (desc[0] & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static void ses_get_locate(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 			   struct enclosure_component *ecomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	unsigned char *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	if (!ses_page2_supported(edev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		ecomp->locate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	desc = ses_get_page2_descriptor(edev, ecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	if (desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		ecomp->locate = (desc[2] & 0x02) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int ses_set_locate(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			  struct enclosure_component *ecomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			  enum enclosure_component_setting val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	unsigned char desc[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	unsigned char *desc_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	if (!ses_page2_supported(edev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	desc_ptr = ses_get_page2_descriptor(edev, ecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if (!desc_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	init_device_slot_control(desc, ecomp, desc_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	case ENCLOSURE_SETTING_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		desc[2] &= 0xfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	case ENCLOSURE_SETTING_ENABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		desc[2] |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		/* SES doesn't do the SGPIO blink settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	return ses_set_page2_descriptor(edev, ecomp, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static int ses_set_active(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 			  struct enclosure_component *ecomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 			  enum enclosure_component_setting val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	unsigned char desc[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	unsigned char *desc_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	if (!ses_page2_supported(edev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	desc_ptr = ses_get_page2_descriptor(edev, ecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	if (!desc_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	init_device_slot_control(desc, ecomp, desc_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	case ENCLOSURE_SETTING_DISABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		desc[2] &= 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		ecomp->active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	case ENCLOSURE_SETTING_ENABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		desc[2] |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		ecomp->active = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		/* SES doesn't do the SGPIO blink settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	return ses_set_page2_descriptor(edev, ecomp, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static int ses_show_id(struct enclosure_device *edev, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	struct ses_device *ses_dev = edev->scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	unsigned long long id = get_unaligned_be64(ses_dev->page1+8+4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	return sprintf(buf, "%#llx\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static void ses_get_power_status(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 				 struct enclosure_component *ecomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	unsigned char *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	if (!ses_page2_supported(edev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		ecomp->power_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	desc = ses_get_page2_descriptor(edev, ecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	if (desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		ecomp->power_status = (desc[3] & 0x10) ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static int ses_set_power_status(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 				struct enclosure_component *ecomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 				int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	unsigned char desc[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	unsigned char *desc_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	if (!ses_page2_supported(edev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	desc_ptr = ses_get_page2_descriptor(edev, ecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	if (!desc_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	init_device_slot_control(desc, ecomp, desc_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	/* power = 1 is device_off = 0 and vice versa */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		desc[3] |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		desc[3] &= 0xef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	ecomp->power_status = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	return ses_set_page2_descriptor(edev, ecomp, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static struct enclosure_component_callbacks ses_enclosure_callbacks = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	.get_fault		= ses_get_fault,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	.set_fault		= ses_set_fault,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	.get_status		= ses_get_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	.get_locate		= ses_get_locate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	.set_locate		= ses_set_locate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	.get_power_status	= ses_get_power_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	.set_power_status	= ses_set_power_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	.set_active		= ses_set_active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	.show_id		= ses_show_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct ses_host_edev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	struct Scsi_Host *shost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	struct enclosure_device *edev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) int ses_match_host(struct enclosure_device *edev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	struct ses_host_edev *sed = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	struct scsi_device *sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	if (!scsi_is_sdev_device(edev->edev.parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	sdev = to_scsi_device(edev->edev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	if (sdev->host != sed->shost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	sed->edev = edev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) #endif  /*  0  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static void ses_process_descriptor(struct enclosure_component *ecomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 				   unsigned char *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	int eip = desc[0] & 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	int invalid = desc[0] & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	enum scsi_protocol proto = desc[0] & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	u64 addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	int slot = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	struct ses_component *scomp = ecomp->scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	unsigned char *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	if (invalid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	switch (proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	case SCSI_PROTOCOL_FCP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		if (eip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 			d = desc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 			slot = d[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	case SCSI_PROTOCOL_SAS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		if (eip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 			d = desc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 			slot = d[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 			d = desc + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 			d = desc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		/* only take the phy0 addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		addr = (u64)d[12] << 56 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 			(u64)d[13] << 48 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 			(u64)d[14] << 40 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 			(u64)d[15] << 32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 			(u64)d[16] << 24 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			(u64)d[17] << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 			(u64)d[18] << 8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 			(u64)d[19];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		/* FIXME: Need to add more protocols than just SAS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	ecomp->slot = slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	scomp->addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct efd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	u64 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static int ses_enclosure_find_by_addr(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 				      void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	struct efd *efd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	struct ses_component *scomp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	if (!edev->component[0].scratch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	for (i = 0; i < edev->components; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		scomp = edev->component[i].scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		if (scomp->addr != efd->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		if (enclosure_add_device(edev, i, efd->dev) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 			kobject_uevent(&efd->dev->kobj, KOBJ_CHANGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) #define INIT_ALLOC_SIZE 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static void ses_enclosure_data_process(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 				       struct scsi_device *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 				       int create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	unsigned char *buf = NULL, *type_ptr, *desc_ptr, *addl_desc_ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	int i, j, page7_len, len, components;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	struct ses_device *ses_dev = edev->scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	int types = ses_dev->page1_num_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	unsigned char *hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	if (!hdr_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		goto simple_populate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	/* re-read page 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	if (ses_dev->page10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		ses_recv_diag(sdev, 10, ses_dev->page10, ses_dev->page10_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	/* Page 7 for the descriptors is optional */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	result = ses_recv_diag(sdev, 7, hdr_buf, INIT_ALLOC_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 		goto simple_populate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	page7_len = len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	/* add 1 for trailing '\0' we'll use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	buf = kzalloc(len + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		goto simple_populate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	result = ses_recv_diag(sdev, 7, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)  simple_populate:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		desc_ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		page7_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		desc_ptr = buf + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		len = (desc_ptr[2] << 8) + desc_ptr[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		/* skip past overall descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		desc_ptr += len + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	if (ses_dev->page10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		addl_desc_ptr = ses_dev->page10 + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	type_ptr = ses_dev->page1_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	components = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	for (i = 0; i < types; i++, type_ptr += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		for (j = 0; j < type_ptr[1]; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			char *name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 			struct enclosure_component *ecomp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 			if (desc_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 				if (desc_ptr >= buf + page7_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 					desc_ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 					len = (desc_ptr[2] << 8) + desc_ptr[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 					desc_ptr += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 					/* Add trailing zero - pushes into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 					 * reserved space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 					desc_ptr[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 					name = desc_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 			if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 			    type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 				if (create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 					ecomp =	enclosure_component_alloc(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 						edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 						components++,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 						type_ptr[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 						name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 					ecomp = &edev->component[components++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 				if (!IS_ERR(ecomp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 					if (addl_desc_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 						ses_process_descriptor(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 							ecomp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 							addl_desc_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 					if (create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 						enclosure_component_register(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 							ecomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 			if (desc_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 				desc_ptr += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 			if (addl_desc_ptr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 			    /* only find additional descriptions for specific devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 			    (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			     type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 			     type_ptr[0] == ENCLOSURE_COMPONENT_SAS_EXPANDER ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 			     /* these elements are optional */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 			     type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 			     type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 			     type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 				addl_desc_ptr += addl_desc_ptr[1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	kfree(hdr_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) static void ses_match_to_enclosure(struct enclosure_device *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 				   struct scsi_device *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 				   int refresh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	struct scsi_device *edev_sdev = to_scsi_device(edev->edev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	struct efd efd = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		.addr = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	if (refresh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		ses_enclosure_data_process(edev, edev_sdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	if (scsi_is_sas_rphy(sdev->sdev_target->dev.parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 		efd.addr = sas_get_address(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	if (efd.addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 		efd.dev = &sdev->sdev_gendev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 		enclosure_for_each_device(ses_enclosure_find_by_addr, &efd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static int ses_intf_add(struct device *cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 			struct class_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	struct scsi_device *sdev = to_scsi_device(cdev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	struct scsi_device *tmp_sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	unsigned char *buf = NULL, *hdr_buf, *type_ptr, page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	struct ses_device *ses_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	u32 result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	int i, types, len, components = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	int num_enclosures;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	struct enclosure_device *edev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	struct ses_component *scomp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	if (!scsi_device_enclosure(sdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 		/* not an enclosure, but might be in one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 		struct enclosure_device *prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 		while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 			ses_match_to_enclosure(edev, sdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 			prev = edev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	/* TYPE_ENCLOSURE prints a message in probe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	if (sdev->type != TYPE_ENCLOSURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		sdev_printk(KERN_NOTICE, sdev, "Embedded Enclosure Device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	ses_dev = kzalloc(sizeof(*ses_dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	if (!hdr_buf || !ses_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 		goto err_init_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	page = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	result = ses_recv_diag(sdev, page, hdr_buf, INIT_ALLOC_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 		goto recv_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	buf = kzalloc(len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 		goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	result = ses_recv_diag(sdev, page, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 		goto recv_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	types = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	/* we always have one main enclosure and the rest are referred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	 * to as secondary subenclosures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	num_enclosures = buf[1] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	/* begin at the enclosure descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	type_ptr = buf + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	/* skip all the enclosure descriptors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	for (i = 0; i < num_enclosures && type_ptr < buf + len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 		types += type_ptr[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 		type_ptr += type_ptr[3] + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	ses_dev->page1_types = type_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	ses_dev->page1_num_types = types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	for (i = 0; i < types && type_ptr < buf + len; i++, type_ptr += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 		if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 		    type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 			components += type_ptr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	ses_dev->page1 = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	ses_dev->page1_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	page = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	result = ses_recv_diag(sdev, page, hdr_buf, INIT_ALLOC_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 		goto page2_not_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	buf = kzalloc(len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 		goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	/* make sure getting page 2 actually works */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 	result = ses_recv_diag(sdev, 2, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 		goto recv_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	ses_dev->page2 = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	ses_dev->page2_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	/* The additional information page --- allows us
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	 * to match up the devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	page = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	result = ses_recv_diag(sdev, page, hdr_buf, INIT_ALLOC_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 	if (!result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 		len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 		buf = kzalloc(len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 		if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 			goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 		result = ses_recv_diag(sdev, page, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 		if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 			goto recv_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 		ses_dev->page10 = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 		ses_dev->page10_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 		buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) page2_not_supported:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	if (!scomp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 				  components, &ses_enclosure_callbacks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	if (IS_ERR(edev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 		err = PTR_ERR(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 		goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	kfree(hdr_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	edev->scratch = ses_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 	for (i = 0; i < components; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 		edev->component[i].scratch = scomp + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	ses_enclosure_data_process(edev, sdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	/* see if there are any devices matching before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 	 * we found the enclosure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	shost_for_each_device(tmp_sdev, sdev->host) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 		if (tmp_sdev->lun != 0 || scsi_device_enclosure(tmp_sdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 		ses_match_to_enclosure(edev, tmp_sdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)  recv_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 	sdev_printk(KERN_ERR, sdev, "Failed to get diagnostic page 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 		    page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 	err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)  err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 	kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 	kfree(scomp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 	kfree(ses_dev->page10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 	kfree(ses_dev->page2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 	kfree(ses_dev->page1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)  err_init_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 	kfree(ses_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 	kfree(hdr_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	sdev_printk(KERN_ERR, sdev, "Failed to bind enclosure %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static int ses_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) static void ses_intf_remove_component(struct scsi_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	struct enclosure_device *edev, *prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 	while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 		prev = edev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 		if (!enclosure_remove_device(edev, &sdev->sdev_gendev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 	if (edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 		put_device(&edev->edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static void ses_intf_remove_enclosure(struct scsi_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	struct enclosure_device *edev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 	struct ses_device *ses_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 	/*  exact match to this enclosure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	edev = enclosure_find(&sdev->sdev_gendev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 	if (!edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 	ses_dev = edev->scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	edev->scratch = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 	kfree(ses_dev->page10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 	kfree(ses_dev->page1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 	kfree(ses_dev->page2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 	kfree(ses_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 	kfree(edev->component[0].scratch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 	put_device(&edev->edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	enclosure_unregister(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static void ses_intf_remove(struct device *cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 			    struct class_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 	struct scsi_device *sdev = to_scsi_device(cdev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 	if (!scsi_device_enclosure(sdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 		ses_intf_remove_component(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 		ses_intf_remove_enclosure(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static struct class_interface ses_interface = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	.add_dev	= ses_intf_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 	.remove_dev	= ses_intf_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) static struct scsi_driver ses_template = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 	.gendrv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 		.name		= "ses",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 		.owner		= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 		.probe		= ses_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 		.remove		= ses_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static int __init ses_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 	err = scsi_register_interface(&ses_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 	err = scsi_register_driver(&ses_template.gendrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 		goto out_unreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)  out_unreg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 	scsi_unregister_interface(&ses_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static void __exit ses_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 	scsi_unregister_driver(&ses_template.gendrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 	scsi_unregister_interface(&ses_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) module_init(ses_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) module_exit(ses_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) MODULE_ALIAS_SCSI_DEVICE(TYPE_ENCLOSURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) MODULE_AUTHOR("James Bottomley");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) MODULE_DESCRIPTION("SCSI Enclosure Services (ses) driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) MODULE_LICENSE("GPL v2");