1 /* 2 * zfcp device driver 3 * 4 * Tracking of manually configured LUNs and helper functions to 5 * register the LUNs with the SCSI midlayer. 6 * 7 * Copyright IBM Corp. 2010 8 */ 9 10 #include "zfcp_def.h" 11 #include "zfcp_ext.h" 12 13 /** 14 * zfcp_unit_scsi_scan - Register LUN with SCSI midlayer 15 * @unit: The zfcp LUN/unit to register 16 * 17 * When the SCSI midlayer is not allowed to automatically scan and 18 * attach SCSI devices, zfcp has to register the single devices with 19 * the SCSI midlayer. 20 */ 21 void zfcp_unit_scsi_scan(struct zfcp_unit *unit) 22 { 23 struct fc_rport *rport = unit->port->rport; 24 u64 lun; 25 26 lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); 27 28 if (rport && rport->port_state == FC_PORTSTATE_ONLINE) 29 scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 30 SCSI_SCAN_MANUAL); 31 } 32 33 static void zfcp_unit_scsi_scan_work(struct work_struct *work) 34 { 35 struct zfcp_unit *unit = container_of(work, struct zfcp_unit, 36 scsi_work); 37 38 zfcp_unit_scsi_scan(unit); 39 put_device(&unit->dev); 40 } 41 42 /** 43 * zfcp_unit_queue_scsi_scan - Register configured units on port 44 * @port: The zfcp_port where to register units 45 * 46 * After opening a port, all units configured on this port have to be 47 * registered with the SCSI midlayer. This function should be called 48 * after calling fc_remote_port_add, so that the fc_rport is already 49 * ONLINE and the call to scsi_scan_target runs the same way as the 50 * call in the FC transport class. 51 */ 52 void zfcp_unit_queue_scsi_scan(struct zfcp_port *port) 53 { 54 struct zfcp_unit *unit; 55 56 read_lock_irq(&port->unit_list_lock); 57 list_for_each_entry(unit, &port->unit_list, list) { 58 get_device(&unit->dev); 59 if (scsi_queue_work(port->adapter->scsi_host, 60 &unit->scsi_work) <= 0) 61 put_device(&unit->dev); 62 } 63 read_unlock_irq(&port->unit_list_lock); 64 } 65 66 static struct zfcp_unit *_zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun) 67 { 68 struct zfcp_unit *unit; 69 70 list_for_each_entry(unit, &port->unit_list, list) 71 if (unit->fcp_lun == fcp_lun) { 72 get_device(&unit->dev); 73 return unit; 74 } 75 76 return NULL; 77 } 78 79 /** 80 * zfcp_unit_find - Find and return zfcp_unit with specified FCP LUN 81 * @port: zfcp_port where to look for the unit 82 * @fcp_lun: 64 Bit FCP LUN used to identify the zfcp_unit 83 * 84 * If zfcp_unit is found, a reference is acquired that has to be 85 * released later. 86 * 87 * Returns: Pointer to the zfcp_unit, or NULL if there is no zfcp_unit 88 * with the specified FCP LUN. 89 */ 90 struct zfcp_unit *zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun) 91 { 92 struct zfcp_unit *unit; 93 94 read_lock_irq(&port->unit_list_lock); 95 unit = _zfcp_unit_find(port, fcp_lun); 96 read_unlock_irq(&port->unit_list_lock); 97 return unit; 98 } 99 100 /** 101 * zfcp_unit_release - Drop reference to zfcp_port and free memory of zfcp_unit. 102 * @dev: pointer to device in zfcp_unit 103 */ 104 static void zfcp_unit_release(struct device *dev) 105 { 106 struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); 107 108 atomic_dec(&unit->port->units); 109 kfree(unit); 110 } 111 112 /** 113 * zfcp_unit_enqueue - enqueue unit to unit list of a port. 114 * @port: pointer to port where unit is added 115 * @fcp_lun: FCP LUN of unit to be enqueued 116 * Returns: 0 success 117 * 118 * Sets up some unit internal structures and creates sysfs entry. 119 */ 120 int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) 121 { 122 struct zfcp_unit *unit; 123 int retval = 0; 124 125 mutex_lock(&zfcp_sysfs_port_units_mutex); 126 if (atomic_read(&port->units) == -1) { 127 /* port is already gone */ 128 retval = -ENODEV; 129 goto out; 130 } 131 132 unit = zfcp_unit_find(port, fcp_lun); 133 if (unit) { 134 put_device(&unit->dev); 135 retval = -EEXIST; 136 goto out; 137 } 138 139 unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); 140 if (!unit) { 141 retval = -ENOMEM; 142 goto out; 143 } 144 145 unit->port = port; 146 unit->fcp_lun = fcp_lun; 147 unit->dev.parent = &port->dev; 148 unit->dev.release = zfcp_unit_release; 149 unit->dev.groups = zfcp_unit_attr_groups; 150 INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work); 151 152 if (dev_set_name(&unit->dev, "0x%016llx", 153 (unsigned long long) fcp_lun)) { 154 kfree(unit); 155 retval = -ENOMEM; 156 goto out; 157 } 158 159 if (device_register(&unit->dev)) { 160 put_device(&unit->dev); 161 retval = -ENOMEM; 162 goto out; 163 } 164 165 atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */ 166 167 write_lock_irq(&port->unit_list_lock); 168 list_add_tail(&unit->list, &port->unit_list); 169 write_unlock_irq(&port->unit_list_lock); 170 171 zfcp_unit_scsi_scan(unit); 172 173 out: 174 mutex_unlock(&zfcp_sysfs_port_units_mutex); 175 return retval; 176 } 177 178 /** 179 * zfcp_unit_sdev - Return SCSI device for zfcp_unit 180 * @unit: The zfcp_unit where to get the SCSI device for 181 * 182 * Returns: scsi_device pointer on success, NULL if there is no SCSI 183 * device for this zfcp_unit 184 * 185 * On success, the caller also holds a reference to the SCSI device 186 * that must be released with scsi_device_put. 187 */ 188 struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit) 189 { 190 struct Scsi_Host *shost; 191 struct zfcp_port *port; 192 u64 lun; 193 194 lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun); 195 port = unit->port; 196 shost = port->adapter->scsi_host; 197 return scsi_device_lookup(shost, 0, port->starget_id, lun); 198 } 199 200 /** 201 * zfcp_unit_sdev_status - Return zfcp LUN status for SCSI device 202 * @unit: The unit to lookup the SCSI device for 203 * 204 * Returns the zfcp LUN status field of the SCSI device if the SCSI device 205 * for the zfcp_unit exists, 0 otherwise. 206 */ 207 unsigned int zfcp_unit_sdev_status(struct zfcp_unit *unit) 208 { 209 unsigned int status = 0; 210 struct scsi_device *sdev; 211 struct zfcp_scsi_dev *zfcp_sdev; 212 213 sdev = zfcp_unit_sdev(unit); 214 if (sdev) { 215 zfcp_sdev = sdev_to_zfcp(sdev); 216 status = atomic_read(&zfcp_sdev->status); 217 scsi_device_put(sdev); 218 } 219 220 return status; 221 } 222 223 /** 224 * zfcp_unit_remove - Remove entry from list of configured units 225 * @port: The port where to remove the unit from the configuration 226 * @fcp_lun: The 64 bit LUN of the unit to remove 227 * 228 * Returns: -EINVAL if a unit with the specified LUN does not exist, 229 * 0 on success. 230 */ 231 int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun) 232 { 233 struct zfcp_unit *unit; 234 struct scsi_device *sdev; 235 236 write_lock_irq(&port->unit_list_lock); 237 unit = _zfcp_unit_find(port, fcp_lun); 238 if (unit) 239 list_del(&unit->list); 240 write_unlock_irq(&port->unit_list_lock); 241 242 if (!unit) 243 return -EINVAL; 244 245 sdev = zfcp_unit_sdev(unit); 246 if (sdev) { 247 scsi_remove_device(sdev); 248 scsi_device_put(sdev); 249 } 250 251 put_device(&unit->dev); 252 253 device_unregister(&unit->dev); 254 255 return 0; 256 } 257