[PATCH 31/44] staging: unisys: Convert device functions to pass dev_info pointer around

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Don Zickus <dzickus@xxxxxxxxxx>

Most device functions pass bus_no and dev_no around and then do a lookup
inside each function to find the dev_info struct.  Instead just pass the
pointer.

This prepares us for a later conversion to using visor device.

No real technical changes.  Just function header changes and little
cleanups as a result.

Signed-off-by: Don Zickus <dzickus@xxxxxxxxxx>
Signed-off-by: Benjamin Romer <benjamin.romer@xxxxxxxxxx>
---
 drivers/staging/unisys/include/visorbus.h          |  8 +-
 drivers/staging/unisys/visorbus/visorbus_main.c    | 95 ++++++++++++----------
 drivers/staging/unisys/visorbus/visorbus_private.h | 17 ++--
 drivers/staging/unisys/visorbus/visorchipset.c     | 74 ++++++++---------
 4 files changed, 103 insertions(+), 91 deletions(-)

diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h
index 3375ffd..3152ba4 100644
--- a/drivers/staging/unisys/include/visorbus.h
+++ b/drivers/staging/unisys/include/visorbus.h
@@ -43,7 +43,7 @@ struct visor_device;
 extern struct bus_type visorbus_type;
 
 typedef void (*visorbus_state_complete_func) (struct visor_device *dev,
-					      int status);
+					      int status, void *dev_info);
 struct visorchipset_state {
 	u32 created:1;
 	u32 attached:1;
@@ -106,9 +106,11 @@ struct visor_driver {
 	 *  fails or completes successfully.
 	 */
 	int (*pause)(struct visor_device *dev,
-		     visorbus_state_complete_func complete_func);
+		     visorbus_state_complete_func complete_func,
+		     void *dev_info);
 	int (*resume)(struct visor_device *dev,
-		      visorbus_state_complete_func complete_func);
+		      visorbus_state_complete_func complete_func,
+		      void *dev_info);
 
 	/** These fields are for private use by the bus driver only. */
 	struct device_driver driver;
diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c
index dd36d7b..a898896 100644
--- a/drivers/staging/unisys/visorbus/visorbus_main.c
+++ b/drivers/staging/unisys/visorbus/visorbus_main.c
@@ -110,10 +110,10 @@ static long long total_devices_created;
 
 static void chipset_bus_create(struct visorchipset_bus_info *bus_info);
 static void chipset_bus_destroy(struct visorchipset_bus_info *bus_info);
-static void chipset_device_create(u32 bus_no, u32 dev_no);
-static void chipset_device_destroy(u32 bus_no, u32 dev_no);
-static void chipset_device_pause(u32 bus_no, u32 dev_no);
-static void chipset_device_resume(u32 bus_no, u32 dev_no);
+static void chipset_device_create(struct visorchipset_device_info *dev_info);
+static void chipset_device_destroy(struct visorchipset_device_info *dev_info);
+static void chipset_device_pause(struct visorchipset_device_info *dev_info);
+static void chipset_device_resume(struct visorchipset_device_info *dev_info);
 
 /** These functions are implemented herein, and are called by the chipset
  *  driver to notify us about specific events.
@@ -813,11 +813,17 @@ away:
 	 *  initialized.
 	 */
 	if (!dev->responded_to_device_create) {
+		struct visorchipset_device_info dev_info;
+
+		if (!visorchipset_get_device_info(dev->chipset_bus_no,
+						  dev->chipset_dev_no,
+						  &dev_info))
+			/* hmm, what to do here */
+			return rc;
+
 		dev->responded_to_device_create = true;
 		if (chipset_responders.device_create)
-			(*chipset_responders.device_create)(dev->chipset_bus_no,
-							    dev->chipset_dev_no,
-							    rc);
+			(*chipset_responders.device_create)(&dev_info, rc);
 	}
 	return rc;
 }
@@ -1003,7 +1009,7 @@ EXPORT_SYMBOL_GPL(visorbus_disable_channel_interrupts);
  */
 static int
 create_visor_device(struct visorbus_devdata *devdata,
-		    unsigned long chipset_bus_no, unsigned long chipset_dev_no,
+		    struct visorchipset_device_info *dev_info,
 		    struct visorchipset_channel_info chan_info,
 		    u64 partition_handle)
 {
@@ -1011,6 +1017,8 @@ create_visor_device(struct visorbus_devdata *devdata,
 	struct visorchannel *visorchannel = NULL;
 	struct visor_device *dev = NULL;
 	bool gotten = false, registered1 = false, registered2 = false;
+	u32 chipset_bus_no = dev_info->bus_no;
+	u32 chipset_dev_no = dev_info->dev_no;
 
 	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, chipset_dev_no, chipset_bus_no,
 			 POSTCODE_SEVERITY_INFO);
@@ -1061,7 +1069,7 @@ create_visor_device(struct visorbus_devdata *devdata,
 	 * (NOT bus instance).  That's why we need to include the bus
 	 * number within the name.
 	 */
-	dev_set_name(&dev->device, "vbus%lu:dev%lu",
+	dev_set_name(&dev->device, "vbus%u:dev%u",
 		     chipset_bus_no, chipset_dev_no);
 
 	/*  device_add does this:
@@ -1512,26 +1520,25 @@ away:
 }
 
 static void
-chipset_device_create(u32 bus_no, u32 dev_no)
+chipset_device_create(struct visorchipset_device_info *dev_info)
 {
-	struct visorchipset_device_info dev_info;
 	struct visorchipset_bus_info bus_info;
 	struct visorbus_devdata *devdata = NULL;
 	int rc = -1;
+	u32 bus_no = dev_info->bus_no;
+	u32 dev_no = dev_info->dev_no;
 
 	POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
 			 POSTCODE_SEVERITY_INFO);
 
 	if (entered_testing_mode)
 		return;
-	if (!visorchipset_get_device_info(bus_no, dev_no, &dev_info))
-		goto away;
 	if (!visorchipset_get_bus_info(bus_no, &bus_info))
 		goto away;
 	if (visorbus_devicetest)
 		if (total_devices_created < MAXDEVICETEST) {
 			test_channel_infos[total_devices_created] =
-			    dev_info.chan_info;
+			    dev_info->chan_info;
 			test_bus_nos[total_devices_created] = bus_no;
 			test_dev_nos[total_devices_created] = dev_no;
 		}
@@ -1545,27 +1552,25 @@ away:
 		return;
 	}
 	devdata = (struct visorbus_devdata *)(bus_info.bus_driver_context);
-	rc = create_visor_device(devdata, bus_no, dev_no,
-				 dev_info.chan_info, bus_info.partition_handle);
+	rc = create_visor_device(devdata, dev_info,
+				 dev_info->chan_info,
+				 bus_info.partition_handle);
 	POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, dev_no, bus_no,
 			 POSTCODE_SEVERITY_INFO);
 	if (rc < 0)
 		if (chipset_responders.device_create)
-			(*chipset_responders.device_create)(bus_no, dev_no, rc);
+			(*chipset_responders.device_create)(dev_info, rc);
 }
 
 static void
-chipset_device_destroy(u32 bus_no, u32 dev_no)
+chipset_device_destroy(struct visorchipset_device_info *dev_info)
 {
-	struct visorchipset_device_info dev_info;
 	struct visor_device *dev;
 	int rc = -1;
 
 	if (entered_testing_mode)
 		return;
-	if (!visorchipset_get_device_info(bus_no, dev_no, &dev_info))
-		goto away;
-	dev = find_visor_device_by_channel(dev_info.chan_info.channel_addr);
+	dev = find_visor_device_by_channel(dev_info->chan_info.channel_addr);
 	if (!dev)
 		goto away;
 	rc = 0;
@@ -1574,7 +1579,7 @@ away:
 			return;
 
 	if (chipset_responders.device_destroy)
-		(*chipset_responders.device_destroy) (bus_no, dev_no, rc);
+		(*chipset_responders.device_destroy) (dev_info, rc);
 	remove_visor_device(dev);
 }
 
@@ -1583,8 +1588,11 @@ away:
  * completed.
  */
 static void
-pause_state_change_complete(struct visor_device *dev, int status)
+pause_state_change_complete(struct visor_device *dev, int status,
+			    void *info)
 {
+	struct visorchipset_device_info *dev_info = info;
+
 	if (!dev->pausing)
 			return;
 
@@ -1595,8 +1603,7 @@ pause_state_change_complete(struct visor_device *dev, int status)
 	/* Notify the chipset driver that the pause is complete, which
 	* will presumably want to send some sort of response to the
 	* initiator. */
-	(*chipset_responders.device_pause) (dev->chipset_bus_no,
-					    dev->chipset_dev_no, status);
+	(*chipset_responders.device_pause) (dev_info, status);
 }
 
 /* This is the callback function specified for a function driver, to
@@ -1604,8 +1611,11 @@ pause_state_change_complete(struct visor_device *dev, int status)
  * completed.
  */
 static void
-resume_state_change_complete(struct visor_device *dev, int status)
+resume_state_change_complete(struct visor_device *dev, int status,
+			     void *info)
 {
+	struct visorchipset_device_info *dev_info = info;
+
 	if (!dev->resuming)
 			return;
 
@@ -1616,8 +1626,7 @@ resume_state_change_complete(struct visor_device *dev, int status)
 	/* Notify the chipset driver that the resume is complete,
 	 * which will presumably want to send some sort of response to
 	 * the initiator. */
-	(*chipset_responders.device_resume) (dev->chipset_bus_no,
-					     dev->chipset_dev_no, status);
+	(*chipset_responders.device_resume) (dev_info, status);
 }
 
 /* Tell the subordinate function driver for a specific device to pause
@@ -1625,13 +1634,14 @@ resume_state_change_complete(struct visor_device *dev, int status)
  * callback function.
  */
 static void
-initiate_chipset_device_pause_resume(u32 bus_no, u32 dev_no, bool is_pause)
+initiate_chipset_device_pause_resume(struct visorchipset_device_info *dev_info,
+				     bool is_pause)
 {
-	struct visorchipset_device_info dev_info;
 	struct visor_device *dev = NULL;
 	int rc = -1, x;
 	struct visor_driver *drv = NULL;
-	void (*notify_func)(u32 bus_no, u32 dev_no, int response) = NULL;
+	void (*notify_func)(struct visorchipset_device_info *dev_info,
+			    int response) = NULL;
 
 	if (is_pause)
 		notify_func = chipset_responders.device_pause;
@@ -1640,10 +1650,7 @@ initiate_chipset_device_pause_resume(u32 bus_no, u32 dev_no, bool is_pause)
 	if (!notify_func)
 			goto away;
 
-	if (!visorchipset_get_device_info(bus_no, dev_no, &dev_info))
-			goto away;
-
-	dev = find_visor_device_by_channel(dev_info.chan_info.channel_addr);
+	dev = find_visor_device_by_channel(dev_info->chan_info.channel_addr);
 	if (!dev)
 			goto away;
 
@@ -1666,7 +1673,8 @@ initiate_chipset_device_pause_resume(u32 bus_no, u32 dev_no, bool is_pause)
 				goto away;
 
 		dev->pausing = true;
-		x = drv->pause(dev, pause_state_change_complete);
+		x = drv->pause(dev, pause_state_change_complete,
+			       (void *)dev_info);
 	} else {
 		/* This should be done at BUS resume time, but an
 		 * existing problem prevents us from ever getting a bus
@@ -1678,7 +1686,8 @@ initiate_chipset_device_pause_resume(u32 bus_no, u32 dev_no, bool is_pause)
 				goto away;
 
 		dev->resuming = true;
-		x = drv->resume(dev, resume_state_change_complete);
+		x = drv->resume(dev, resume_state_change_complete,
+				(void *)dev_info);
 	}
 	if (x < 0) {
 		if (is_pause)
@@ -1691,20 +1700,20 @@ initiate_chipset_device_pause_resume(u32 bus_no, u32 dev_no, bool is_pause)
 away:
 	if (rc < 0) {
 		if (notify_func)
-				(*notify_func)(bus_no, dev_no, rc);
+				(*notify_func)(dev_info, rc);
 	}
 }
 
 static void
-chipset_device_pause(u32 bus_no, u32 dev_no)
+chipset_device_pause(struct visorchipset_device_info *dev_info)
 {
-	initiate_chipset_device_pause_resume(bus_no, dev_no, true);
+	initiate_chipset_device_pause_resume(dev_info, true);
 }
 
 static void
-chipset_device_resume(u32 bus_no, u32 dev_no)
+chipset_device_resume(struct visorchipset_device_info *dev_info)
 {
-	initiate_chipset_device_pause_resume(bus_no, dev_no, false);
+	initiate_chipset_device_pause_resume(dev_info, false);
 }
 
 struct channel_size_info {
diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h
index 9a2d563..81e4e8c 100644
--- a/drivers/staging/unisys/visorbus/visorbus_private.h
+++ b/drivers/staging/unisys/visorbus/visorbus_private.h
@@ -106,10 +106,10 @@ struct visorchipset_bus_info {
 struct visorchipset_busdev_notifiers {
 	void (*bus_create)(struct visorchipset_bus_info *bus_info);
 	void (*bus_destroy)(struct visorchipset_bus_info *bus_info);
-	void (*device_create)(u32 bus_no, u32 dev_no);
-	void (*device_destroy)(u32 bus_no, u32 dev_no);
-	void (*device_pause)(u32 bus_no, u32 dev_no);
-	void (*device_resume)(u32 bus_no, u32 dev_no);
+	void (*device_create)(struct visorchipset_device_info *bus_info);
+	void (*device_destroy)(struct visorchipset_device_info *bus_info);
+	void (*device_pause)(struct visorchipset_device_info *bus_info);
+	void (*device_resume)(struct visorchipset_device_info *bus_info);
 };
 
 /*  These functions live inside visorchipset, and will be called to indicate
@@ -121,10 +121,11 @@ struct visorchipset_busdev_notifiers {
 struct visorchipset_busdev_responders {
 	void (*bus_create)(struct visorchipset_bus_info *p, int response);
 	void (*bus_destroy)(struct visorchipset_bus_info *p, int response);
-	void (*device_create)(u32 bus_no, u32 dev_no, int response);
-	void (*device_destroy)(u32 bus_no, u32 dev_no, int response);
-	void (*device_pause)(u32 bus_no, u32 dev_no, int response);
-	void (*device_resume)(u32 bus_no, u32 dev_no, int response);
+	void (*device_create)(struct visorchipset_device_info *p, int response);
+	void (*device_destroy)(struct visorchipset_device_info *p,
+			       int response);
+	void (*device_pause)(struct visorchipset_device_info *p, int response);
+	void (*device_resume)(struct visorchipset_device_info *p, int response);
 };
 
 /** Register functions (in the bus driver) to get called by visorchipset
diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c
index 432158d..9bbc080 100644
--- a/drivers/staging/unisys/visorbus/visorchipset.c
+++ b/drivers/staging/unisys/visorbus/visorchipset.c
@@ -230,12 +230,16 @@ static struct visorchipset_busdev_notifiers busdev_notifiers;
 
 static void bus_create_response(struct visorchipset_bus_info *p, int response);
 static void bus_destroy_response(struct visorchipset_bus_info *p, int response);
-static void device_create_response(u32 bus_no, u32 dev_no, int response);
-static void device_destroy_response(u32 bus_no, u32 dev_no, int response);
-static void device_resume_response(u32 bus_no, u32 dev_no, int response);
+static void device_create_response(struct visorchipset_device_info *p,
+				   int response);
+static void device_destroy_response(struct visorchipset_device_info *p,
+				    int response);
+static void device_resume_response(struct visorchipset_device_info *p,
+				   int response);
 
-static void visorchipset_device_pause_response(u32 bus_no, u32 dev_no,
-					       int response);
+static void
+visorchipset_device_pause_response(struct visorchipset_device_info *p,
+				   int response);
 
 static struct visorchipset_busdev_responders busdev_responders = {
 	.bus_create = bus_create_response,
@@ -993,13 +997,13 @@ bus_responder(enum controlvm_id cmd_id, struct visorchipset_bus_info *p,
 
 static void
 device_changestate_responder(enum controlvm_id cmd_id,
-			     u32 bus_no, u32 dev_no, int response,
+			     struct visorchipset_device_info *p, int response,
 			     struct spar_segment_state response_state)
 {
-	struct visorchipset_device_info *p;
 	struct controlvm_message outmsg;
+	u32 bus_no = p->bus_no;
+	u32 dev_no = p->dev_no;
 
-	p = device_find(&dev_info_list, bus_no, dev_no);
 	if (!p)
 		return;
 	if (p->pending_msg_hdr.id == CONTROLVM_INVALID)
@@ -1021,12 +1025,11 @@ device_changestate_responder(enum controlvm_id cmd_id,
 }
 
 static void
-device_responder(enum controlvm_id cmd_id, u32 bus_no, u32 dev_no, int response)
+device_responder(enum controlvm_id cmd_id, struct visorchipset_device_info *p,
+		 int response)
 {
-	struct visorchipset_device_info *p;
 	bool need_clear = false;
 
-	p = device_find(&dev_info_list, bus_no, dev_no);
 	if (!p)
 		return;
 	if (response >= 0) {
@@ -1094,15 +1097,16 @@ bus_epilog(struct visorchipset_bus_info *bus_info,
 }
 
 static void
-device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd,
+device_epilog(struct visorchipset_device_info *dev_info,
+	      struct spar_segment_state state, u32 cmd,
 	      struct controlvm_message_header *msg_hdr, int response,
 	      bool need_response, bool for_visorbus)
 {
 	struct visorchipset_busdev_notifiers *notifiers;
 	bool notified = false;
+	u32 bus_no = dev_info->bus_no;
+	u32 dev_no = dev_info->dev_no;
 
-	struct visorchipset_device_info *dev_info =
-		device_find(&dev_info_list, bus_no, dev_no);
 	char *envp[] = {
 		"SPARSP_DIAGPOOL_PAUSED_STATE = 1",
 		NULL
@@ -1125,7 +1129,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd,
 		switch (cmd) {
 		case CONTROLVM_DEVICE_CREATE:
 			if (notifiers->device_create) {
-				(*notifiers->device_create) (bus_no, dev_no);
+				(*notifiers->device_create) (dev_info);
 				notified = true;
 			}
 			break;
@@ -1135,8 +1139,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd,
 			    state.operating ==
 				segment_state_running.operating) {
 				if (notifiers->device_resume) {
-					(*notifiers->device_resume) (bus_no,
-								     dev_no);
+					(*notifiers->device_resume) (dev_info);
 					notified = true;
 				}
 			}
@@ -1148,8 +1151,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd,
 				 * where server is lost
 				 */
 				if (notifiers->device_pause) {
-					(*notifiers->device_pause) (bus_no,
-								    dev_no);
+					(*notifiers->device_pause) (dev_info);
 					notified = true;
 				}
 			} else if (state.alive == segment_state_paused.alive &&
@@ -1171,7 +1173,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd,
 			break;
 		case CONTROLVM_DEVICE_DESTROY:
 			if (notifiers->device_destroy) {
-				(*notifiers->device_destroy) (bus_no, dev_no);
+				(*notifiers->device_destroy) (dev_info);
 				notified = true;
 			}
 			break;
@@ -1184,7 +1186,7 @@ device_epilog(u32 bus_no, u32 dev_no, struct spar_segment_state state, u32 cmd,
 		 */
 		;
 	else
-		device_responder(cmd, bus_no, dev_no, response);
+		device_responder(cmd, dev_info, response);
 	up(&notifier_lock);
 }
 
@@ -1359,7 +1361,7 @@ cleanup:
 		g_diagpool_bus_no = bus_no;
 		g_diagpool_dev_no = dev_no;
 	}
-	device_epilog(bus_no, dev_no, segment_state_running,
+	device_epilog(dev_info, segment_state_running,
 		      CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
 		      inmsg->hdr.flags.response_expected == 1, 1);
 }
@@ -1385,7 +1387,7 @@ my_device_changestate(struct controlvm_message *inmsg)
 		rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
 	}
 	if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
-		device_epilog(bus_no, dev_no, state,
+		device_epilog(dev_info, state,
 			      CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc,
 			      inmsg->hdr.flags.response_expected == 1, 1);
 }
@@ -1406,7 +1408,7 @@ my_device_destroy(struct controlvm_message *inmsg)
 		rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
 
 	if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
-		device_epilog(bus_no, dev_no, segment_state_running,
+		device_epilog(dev_info, segment_state_running,
 			      CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
 			      inmsg->hdr.flags.response_expected == 1, 1);
 }
@@ -2121,30 +2123,31 @@ bus_destroy_response(struct visorchipset_bus_info *bus_info, int response)
 }
 
 static void
-device_create_response(u32 bus_no, u32 dev_no, int response)
+device_create_response(struct visorchipset_device_info *dev_info, int response)
 {
-	device_responder(CONTROLVM_DEVICE_CREATE, bus_no, dev_no, response);
+	device_responder(CONTROLVM_DEVICE_CREATE, dev_info, response);
 }
 
 static void
-device_destroy_response(u32 bus_no, u32 dev_no, int response)
+device_destroy_response(struct visorchipset_device_info *dev_info, int response)
 {
-	device_responder(CONTROLVM_DEVICE_DESTROY, bus_no, dev_no, response);
+	device_responder(CONTROLVM_DEVICE_DESTROY, dev_info, response);
 }
 
 static void
-visorchipset_device_pause_response(u32 bus_no, u32 dev_no, int response)
+visorchipset_device_pause_response(struct visorchipset_device_info *dev_info,
+				   int response)
 {
 	device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
-				     bus_no, dev_no, response,
+				     dev_info, response,
 				     segment_state_standby);
 }
 
 static void
-device_resume_response(u32 bus_no, u32 dev_no, int response)
+device_resume_response(struct visorchipset_device_info *dev_info, int response)
 {
 	device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
-				     bus_no, dev_no, response,
+				     dev_info, response,
 				     segment_state_running);
 }
 
@@ -2184,12 +2187,9 @@ visorchipset_get_device_info(u32 bus_no, u32 dev_no,
 EXPORT_SYMBOL_GPL(visorchipset_get_device_info);
 
 bool
-visorchipset_set_device_context(u32 bus_no, u32 dev_no, void *context)
+visorchipset_set_device_context(struct visorchipset_device_info *p,
+				void *context)
 {
-	struct visorchipset_device_info *p;
-
-	p = device_find(&dev_info_list, bus_no, dev_no);
-
 	if (!p)
 		return false;
 	p->bus_driver_context = context;
-- 
2.1.4

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux