X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fscsi%2Fscsi_transport_sas.c;h=43a964d635b4e19b30d5d76c4dafcc090e8a5a14;hb=8976b6fd7a0060f72e20d5cec833c03d50874cd1;hp=b2ef71a86292c6477dacc38ee7e4f37c960be9f2;hpb=874ff01bd9183ad16495acfd54e93a619d12b8b5;p=linux-2.6 diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index b2ef71a862..43a964d635 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -6,7 +6,7 @@ * * The SAS transport class contains common code to deal with SAS HBAs, * an aproximated representation of SAS topologies in the driver model, - * and various sysfs attributes to expose these topologies and managment + * and various sysfs attributes to expose these topologies and management * interfaces to userspace. * * In addition to the basic SCSI core objects this transport class @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -40,6 +42,7 @@ struct sas_host_attrs { struct list_head rphy_list; struct mutex lock; + struct request_queue *q; u32 next_target_id; u32 next_expander_id; int next_port_id; @@ -152,6 +155,107 @@ static struct { sas_bitfield_name_search(linkspeed, sas_linkspeed_names) sas_bitfield_name_set(linkspeed, sas_linkspeed_names) +static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, + struct sas_rphy *rphy) +{ + struct request *req; + int ret; + int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *); + + while (!blk_queue_plugged(q)) { + req = elv_next_request(q); + if (!req) + break; + + blkdev_dequeue_request(req); + + spin_unlock_irq(q->queue_lock); + + handler = to_sas_internal(shost->transportt)->f->smp_handler; + ret = handler(shost, rphy, req); + req->errors = ret; + + spin_lock_irq(q->queue_lock); + + req->end_io(req, ret); + } +} + +static void sas_host_smp_request(struct request_queue *q) +{ + sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL); +} + +static void sas_non_host_smp_request(struct request_queue *q) +{ + struct sas_rphy *rphy = q->queuedata; + sas_smp_request(q, rphy_to_shost(rphy), rphy); +} + +static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) +{ + struct request_queue *q; + int error; + struct device *dev; + char namebuf[BUS_ID_SIZE]; + const char *name; + + if (!to_sas_internal(shost->transportt)->f->smp_handler) { + printk("%s can't handle SMP requests\n", shost->hostt->name); + return 0; + } + + if (rphy) { + q = blk_init_queue(sas_non_host_smp_request, NULL); + dev = &rphy->dev; + name = dev->bus_id; + } else { + q = blk_init_queue(sas_host_smp_request, NULL); + dev = &shost->shost_gendev; + snprintf(namebuf, sizeof(namebuf), + "sas_host%d", shost->host_no); + name = namebuf; + } + if (!q) + return -ENOMEM; + + error = bsg_register_queue(q, dev, name); + if (error) { + blk_cleanup_queue(q); + return -ENOMEM; + } + + if (rphy) + rphy->q = q; + else + to_sas_host_attrs(shost)->q = q; + + if (rphy) + q->queuedata = rphy; + else + q->queuedata = shost; + + set_bit(QUEUE_FLAG_BIDI, &q->queue_flags); + + return 0; +} + +static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy) +{ + struct request_queue *q; + + if (rphy) + q = rphy->q; + else + q = to_sas_host_attrs(shost)->q; + + if (!q) + return; + + bsg_unregister_queue(q); + blk_cleanup_queue(q); +} + /* * SAS host attributes */ @@ -167,11 +271,26 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, sas_host->next_target_id = 0; sas_host->next_expander_id = 0; sas_host->next_port_id = 0; + + if (sas_bsg_initialize(shost, NULL)) + dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n", + shost->host_no); + + return 0; +} + +static int sas_host_remove(struct transport_container *tc, struct device *dev, + struct class_device *cdev) +{ + struct Scsi_Host *shost = dev_to_shost(dev); + + sas_bsg_remove(shost, NULL); + return 0; } static DECLARE_TRANSPORT_CLASS(sas_host_class, - "sas_host", sas_host_setup, NULL, NULL); + "sas_host", sas_host_setup, sas_host_remove, NULL); static int sas_host_match(struct attribute_container *cont, struct device *dev) @@ -205,7 +324,7 @@ static int do_sas_phy_delete(struct device *dev, void *data) } /** - * sas_remove_children -- tear down a devices SAS data structures + * sas_remove_children - tear down a devices SAS data structures * @dev: device belonging to the sas object * * Removes all SAS PHYs and remote PHYs for a given object @@ -218,7 +337,7 @@ void sas_remove_children(struct device *dev) EXPORT_SYMBOL(sas_remove_children); /** - * sas_remove_host -- tear down a Scsi_Host's SAS data structures + * sas_remove_host - tear down a Scsi_Host's SAS data structures * @shost: Scsi Host that is torn down * * Removes all SAS PHYs and remote PHYs for a given Scsi_Host. @@ -459,7 +578,7 @@ static void sas_phy_release(struct device *dev) } /** - * sas_phy_alloc -- allocates and initialize a SAS PHY structure + * sas_phy_alloc - allocates and initialize a SAS PHY structure * @parent: Parent device * @number: Phy index * @@ -500,7 +619,7 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number) EXPORT_SYMBOL(sas_phy_alloc); /** - * sas_phy_add -- add a SAS PHY to the device hierarchy + * sas_phy_add - add a SAS PHY to the device hierarchy * @phy: The PHY to be added * * Publishes a SAS PHY to the rest of the system. @@ -520,7 +639,7 @@ int sas_phy_add(struct sas_phy *phy) EXPORT_SYMBOL(sas_phy_add); /** - * sas_phy_free -- free a SAS PHY + * sas_phy_free - free a SAS PHY * @phy: SAS PHY to free * * Frees the specified SAS PHY. @@ -537,7 +656,7 @@ void sas_phy_free(struct sas_phy *phy) EXPORT_SYMBOL(sas_phy_free); /** - * sas_phy_delete -- remove SAS PHY + * sas_phy_delete - remove SAS PHY * @phy: SAS PHY to remove * * Removes the specified SAS PHY. If the SAS PHY has an @@ -559,7 +678,7 @@ sas_phy_delete(struct sas_phy *phy) EXPORT_SYMBOL(sas_phy_delete); /** - * scsi_is_sas_phy -- check if a struct device represents a SAS PHY + * scsi_is_sas_phy - check if a struct device represents a SAS PHY * @dev: device to check * * Returns: @@ -725,7 +844,6 @@ EXPORT_SYMBOL(sas_port_alloc_num); /** * sas_port_add - add a SAS port to the device hierarchy - * * @port: port to be added * * publishes a port to the rest of the system @@ -750,7 +868,7 @@ int sas_port_add(struct sas_port *port) EXPORT_SYMBOL(sas_port_add); /** - * sas_port_free -- free a SAS PORT + * sas_port_free - free a SAS PORT * @port: SAS PORT to free * * Frees the specified SAS PORT. @@ -767,7 +885,7 @@ void sas_port_free(struct sas_port *port) EXPORT_SYMBOL(sas_port_free); /** - * sas_port_delete -- remove SAS PORT + * sas_port_delete - remove SAS PORT * @port: SAS PORT to remove * * Removes the specified SAS PORT. If the SAS PORT has an @@ -806,7 +924,7 @@ void sas_port_delete(struct sas_port *port) EXPORT_SYMBOL(sas_port_delete); /** - * scsi_is_sas_port -- check if a struct device represents a SAS port + * scsi_is_sas_port - check if a struct device represents a SAS port * @dev: device to check * * Returns: @@ -1191,6 +1309,7 @@ static void sas_rphy_initialize(struct sas_rphy *rphy) /** * sas_end_device_alloc - allocate an rphy for an end device + * @parent: which port * * Allocates an SAS remote PHY structure, connected to @parent. * @@ -1227,6 +1346,8 @@ EXPORT_SYMBOL(sas_end_device_alloc); /** * sas_expander_alloc - allocate an rphy for an end device + * @parent: which port + * @type: SAS_EDGE_EXPANDER_DEVICE or SAS_FANOUT_EXPANDER_DEVICE * * Allocates an SAS remote PHY structure, connected to @parent. * @@ -1265,7 +1386,7 @@ struct sas_rphy *sas_expander_alloc(struct sas_port *parent, EXPORT_SYMBOL(sas_expander_alloc); /** - * sas_rphy_add -- add a SAS remote PHY to the device hierarchy + * sas_rphy_add - add a SAS remote PHY to the device hierarchy * @rphy: The remote PHY to be added * * Publishes a SAS remote PHY to the rest of the system. @@ -1287,6 +1408,9 @@ int sas_rphy_add(struct sas_rphy *rphy) return error; transport_add_device(&rphy->dev); transport_configure_device(&rphy->dev); + if (sas_bsg_initialize(shost, rphy)) + printk("fail to a bsg device %s\n", rphy->dev.bus_id); + mutex_lock(&sas_host->lock); list_add_tail(&rphy->list, &sas_host->rphy_list); @@ -1309,8 +1433,8 @@ int sas_rphy_add(struct sas_rphy *rphy) EXPORT_SYMBOL(sas_rphy_add); /** - * sas_rphy_free -- free a SAS remote PHY - * @rphy SAS remote PHY to free + * sas_rphy_free - free a SAS remote PHY + * @rphy: SAS remote PHY to free * * Frees the specified SAS remote PHY. * @@ -1329,6 +1453,8 @@ void sas_rphy_free(struct sas_rphy *rphy) list_del(&rphy->list); mutex_unlock(&sas_host->lock); + sas_bsg_remove(shost, rphy); + transport_destroy_device(dev); put_device(dev); @@ -1336,7 +1462,7 @@ void sas_rphy_free(struct sas_rphy *rphy) EXPORT_SYMBOL(sas_rphy_free); /** - * sas_rphy_delete -- remove and free SAS remote PHY + * sas_rphy_delete - remove and free SAS remote PHY * @rphy: SAS remote PHY to remove and free * * Removes the specified SAS remote PHY and frees it. @@ -1350,7 +1476,7 @@ sas_rphy_delete(struct sas_rphy *rphy) EXPORT_SYMBOL(sas_rphy_delete); /** - * sas_rphy_remove -- remove SAS remote PHY + * sas_rphy_remove - remove SAS remote PHY * @rphy: SAS remote phy to remove * * Removes the specified SAS remote PHY. @@ -1381,7 +1507,7 @@ sas_rphy_remove(struct sas_rphy *rphy) EXPORT_SYMBOL(sas_rphy_remove); /** - * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY + * scsi_is_sas_rphy - check if a struct device represents a SAS remote PHY * @dev: device to check * * Returns: @@ -1481,7 +1607,7 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) /** - * sas_attach_transport -- instantiate SAS transport template + * sas_attach_transport - instantiate SAS transport template * @ft: SAS transport class function template */ struct scsi_transport_template * @@ -1592,7 +1718,7 @@ sas_attach_transport(struct sas_function_template *ft) EXPORT_SYMBOL(sas_attach_transport); /** - * sas_release_transport -- release SAS transport template instance + * sas_release_transport - release SAS transport template instance * @t: transport template instance */ void sas_release_transport(struct scsi_transport_template *t)