Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * zfcp device driver
0004  *
0005  * Tracking of manually configured LUNs and helper functions to
0006  * register the LUNs with the SCSI midlayer.
0007  *
0008  * Copyright IBM Corp. 2010
0009  */
0010 
0011 #include "zfcp_def.h"
0012 #include "zfcp_ext.h"
0013 
0014 /**
0015  * zfcp_unit_scsi_scan - Register LUN with SCSI midlayer
0016  * @unit: The zfcp LUN/unit to register
0017  *
0018  * When the SCSI midlayer is not allowed to automatically scan and
0019  * attach SCSI devices, zfcp has to register the single devices with
0020  * the SCSI midlayer.
0021  */
0022 void zfcp_unit_scsi_scan(struct zfcp_unit *unit)
0023 {
0024     struct fc_rport *rport = unit->port->rport;
0025     u64 lun;
0026 
0027     lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
0028 
0029     if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
0030         scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun,
0031                  SCSI_SCAN_MANUAL);
0032 }
0033 
0034 static void zfcp_unit_scsi_scan_work(struct work_struct *work)
0035 {
0036     struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
0037                           scsi_work);
0038 
0039     zfcp_unit_scsi_scan(unit);
0040     put_device(&unit->dev);
0041 }
0042 
0043 /**
0044  * zfcp_unit_queue_scsi_scan - Register configured units on port
0045  * @port: The zfcp_port where to register units
0046  *
0047  * After opening a port, all units configured on this port have to be
0048  * registered with the SCSI midlayer. This function should be called
0049  * after calling fc_remote_port_add, so that the fc_rport is already
0050  * ONLINE and the call to scsi_scan_target runs the same way as the
0051  * call in the FC transport class.
0052  */
0053 void zfcp_unit_queue_scsi_scan(struct zfcp_port *port)
0054 {
0055     struct zfcp_unit *unit;
0056 
0057     read_lock_irq(&port->unit_list_lock);
0058     list_for_each_entry(unit, &port->unit_list, list) {
0059         get_device(&unit->dev);
0060         if (scsi_queue_work(port->adapter->scsi_host,
0061                     &unit->scsi_work) <= 0)
0062             put_device(&unit->dev);
0063     }
0064     read_unlock_irq(&port->unit_list_lock);
0065 }
0066 
0067 static struct zfcp_unit *_zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
0068 {
0069     struct zfcp_unit *unit;
0070 
0071     list_for_each_entry(unit, &port->unit_list, list)
0072         if (unit->fcp_lun == fcp_lun) {
0073             get_device(&unit->dev);
0074             return unit;
0075         }
0076 
0077     return NULL;
0078 }
0079 
0080 /**
0081  * zfcp_unit_find - Find and return zfcp_unit with specified FCP LUN
0082  * @port: zfcp_port where to look for the unit
0083  * @fcp_lun: 64 Bit FCP LUN used to identify the zfcp_unit
0084  *
0085  * If zfcp_unit is found, a reference is acquired that has to be
0086  * released later.
0087  *
0088  * Returns: Pointer to the zfcp_unit, or NULL if there is no zfcp_unit
0089  *          with the specified FCP LUN.
0090  */
0091 struct zfcp_unit *zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
0092 {
0093     struct zfcp_unit *unit;
0094 
0095     read_lock_irq(&port->unit_list_lock);
0096     unit = _zfcp_unit_find(port, fcp_lun);
0097     read_unlock_irq(&port->unit_list_lock);
0098     return unit;
0099 }
0100 
0101 /**
0102  * zfcp_unit_release - Drop reference to zfcp_port and free memory of zfcp_unit.
0103  * @dev: pointer to device in zfcp_unit
0104  */
0105 static void zfcp_unit_release(struct device *dev)
0106 {
0107     struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
0108 
0109     atomic_dec(&unit->port->units);
0110     kfree(unit);
0111 }
0112 
0113 /**
0114  * zfcp_unit_add - add unit to unit list of a port.
0115  * @port: pointer to port where unit is added
0116  * @fcp_lun: FCP LUN of unit to be added
0117  * Returns: 0 success
0118  *
0119  * Sets up some unit internal structures and creates sysfs entry.
0120  */
0121 int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
0122 {
0123     struct zfcp_unit *unit;
0124     int retval = 0;
0125 
0126     mutex_lock(&zfcp_sysfs_port_units_mutex);
0127     if (zfcp_sysfs_port_is_removing(port)) {
0128         /* port is already gone */
0129         retval = -ENODEV;
0130         goto out;
0131     }
0132 
0133     unit = zfcp_unit_find(port, fcp_lun);
0134     if (unit) {
0135         put_device(&unit->dev);
0136         retval = -EEXIST;
0137         goto out;
0138     }
0139 
0140     unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
0141     if (!unit) {
0142         retval = -ENOMEM;
0143         goto out;
0144     }
0145 
0146     unit->port = port;
0147     unit->fcp_lun = fcp_lun;
0148     unit->dev.parent = &port->dev;
0149     unit->dev.release = zfcp_unit_release;
0150     unit->dev.groups = zfcp_unit_attr_groups;
0151     INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work);
0152 
0153     if (dev_set_name(&unit->dev, "0x%016llx",
0154              (unsigned long long) fcp_lun)) {
0155         kfree(unit);
0156         retval = -ENOMEM;
0157         goto out;
0158     }
0159 
0160     if (device_register(&unit->dev)) {
0161         put_device(&unit->dev);
0162         retval = -ENOMEM;
0163         goto out;
0164     }
0165 
0166     atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */
0167 
0168     write_lock_irq(&port->unit_list_lock);
0169     list_add_tail(&unit->list, &port->unit_list);
0170     write_unlock_irq(&port->unit_list_lock);
0171     /*
0172      * lock order: shost->scan_mutex before zfcp_sysfs_port_units_mutex
0173      * due to      zfcp_unit_scsi_scan() => zfcp_scsi_slave_alloc()
0174      */
0175     mutex_unlock(&zfcp_sysfs_port_units_mutex);
0176 
0177     zfcp_unit_scsi_scan(unit);
0178     return retval;
0179 
0180 out:
0181     mutex_unlock(&zfcp_sysfs_port_units_mutex);
0182     return retval;
0183 }
0184 
0185 /**
0186  * zfcp_unit_sdev - Return SCSI device for zfcp_unit
0187  * @unit: The zfcp_unit where to get the SCSI device for
0188  *
0189  * Returns: scsi_device pointer on success, NULL if there is no SCSI
0190  *          device for this zfcp_unit
0191  *
0192  * On success, the caller also holds a reference to the SCSI device
0193  * that must be released with scsi_device_put.
0194  */
0195 struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit)
0196 {
0197     struct Scsi_Host *shost;
0198     struct zfcp_port *port;
0199     u64 lun;
0200 
0201     lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
0202     port = unit->port;
0203     shost = port->adapter->scsi_host;
0204     return scsi_device_lookup(shost, 0, port->starget_id, lun);
0205 }
0206 
0207 /**
0208  * zfcp_unit_sdev_status - Return zfcp LUN status for SCSI device
0209  * @unit: The unit to lookup the SCSI device for
0210  *
0211  * Returns the zfcp LUN status field of the SCSI device if the SCSI device
0212  * for the zfcp_unit exists, 0 otherwise.
0213  */
0214 unsigned int zfcp_unit_sdev_status(struct zfcp_unit *unit)
0215 {
0216     unsigned int status = 0;
0217     struct scsi_device *sdev;
0218     struct zfcp_scsi_dev *zfcp_sdev;
0219 
0220     sdev = zfcp_unit_sdev(unit);
0221     if (sdev) {
0222         zfcp_sdev = sdev_to_zfcp(sdev);
0223         status = atomic_read(&zfcp_sdev->status);
0224         scsi_device_put(sdev);
0225     }
0226 
0227     return status;
0228 }
0229 
0230 /**
0231  * zfcp_unit_remove - Remove entry from list of configured units
0232  * @port: The port where to remove the unit from the configuration
0233  * @fcp_lun: The 64 bit LUN of the unit to remove
0234  *
0235  * Returns: -EINVAL if a unit with the specified LUN does not exist,
0236  *          0 on success.
0237  */
0238 int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun)
0239 {
0240     struct zfcp_unit *unit;
0241     struct scsi_device *sdev;
0242 
0243     write_lock_irq(&port->unit_list_lock);
0244     unit = _zfcp_unit_find(port, fcp_lun);
0245     if (unit)
0246         list_del(&unit->list);
0247     write_unlock_irq(&port->unit_list_lock);
0248 
0249     if (!unit)
0250         return -EINVAL;
0251 
0252     sdev = zfcp_unit_sdev(unit);
0253     if (sdev) {
0254         scsi_remove_device(sdev);
0255         scsi_device_put(sdev);
0256     }
0257 
0258     device_unregister(&unit->dev);
0259 
0260     put_device(&unit->dev); /* undo _zfcp_unit_find() */
0261 
0262     return 0;
0263 }