text:
Firearms Discussion by State
Utah Discussion and Firearm News
UT DPS urges UT lawmakers... no more non-resident permits.
Thread starter Quiet
Yrose
I'm in Texas and got my Utah license. The main reason is cost. I'm the sole supporter for my family and when you factor the original Texas fees and class and all the renewal fees and classes that's a good chunk of change!
What's the latest on this?
milboltnut
unless your state doesn't issue permits. If they do then you must obtain your own first.
torontogunguy
ProtectedBy9mm said:
Thats sure is too bad for those American aged 18-21 if this happens, eh? Their rights just gets infringed then?
I had several friends give their lives in their service to their country in the late 60's, 1970. I find it totally absurd that we can be handed a gun and told to kill for our country at 18, but cannot qualify for a concealed carry permit to protect ourselves until 21. It was a long time ago but it is always just like yesterday and the insults continue. How absurd is it to be able to kill for your country yet not purchase a beer until you are 21? Let's get with the programme. The founding fathers enacted the Second Amendment for a reason, not the least of which was to protect ourselves, our property and our families. I am for Constitutional Carry with a means to weed out the felons and whackos.
Yes, they have changed it that you must have your state license to get or renew a Utah non-resident license. I will have to get a Texas license before I can renew mine. I think it's wrong, but have no choice at this time. I am interested how it will be affected if the national bill goes through though.
Yrose said:
One of the problems with the hodge-podge of state laws is it is difficult to get a handle and remember all of the reciprocity agreements and non-res rules. I think the rule in Utah is... if your state issues a permit you must have it before Utah will issue a non-res permit. However, I have to go back and have a look as it may actually say that "IF YOUR STATE RECOGNIZES the Utah permit you must have a permit from your state first".
I will read the actual statute revisions and report back. I am an expert in Utah English and legalspeak.
Had a feeling this might happen. Lot's of people getting the permits for their recipocity value.
torontogunguy said:
The rule appears to be that in order to get a non-res permit, IF you are from a state that has reciprocity or is recognized by Utah, you MUST have your home state's permit first. For instance, if you live in New York State you have no problem renewing as NY has no reciprocity with UTAH. You NEED the Utah permit in order to carry in Utah therefore. Here is the wording of the section of the Utah code:
(4) (a) In addition to meeting the other qualifications for the issuance of a concealed
firearm permit under this section, a nonresident applicant who resides in a state that recognizes the validity of the Utah permit or has reciprocity with Utah's concealed firearm permit law shall:
(i) hold a current concealed firearm or concealed weapon permit issued by the appropriate permitting authority of the nonresident applicant's state of residency; and
(ii) submit a photocopy or electronic copy of the nonresident applicant's current concealed firearm or concealed weapon permit referred to in Subsection (4)(a)(i).
(b) A nonresident applicant who knowingly and willfully provides false information to the bureau under Subsection (4)(a) is prohibited from holding a Utah concealed firearm permit for a period of 10 years.
(c) Subsection (4)(a) applies to all applications for the issuance of a concealed firearm permit that are received by the bureau after May 10, 2011.
(d) Beginning January 1, 2012, Subsection (4)(a) also applies to an application for renewal of a concealed firearm permit by a nonresident.
BC1 said:
I was born in New York. Am a US citizen. Yet I am not permitted to even apply for a permit to carry in New York as I do not reside there. What's with that?
New York State needs to do more in reciprocity. Persons who have a permit and move from the state are now being allowed to keep their NYS permit in case they return for visits and such. At least that's some ground we're making.
G50AE
New York State needs to do more in reciprocity.
Good luck with that one.

redpajama_set_name: RedPajamaCommonCrawl


text:
«Кулевчи» — парусный 60-пушечный фрегат Черноморского флота Российской империи. Участник Синопского сражения 18 ноября 1853 года. Назван в память о победе русских войск под командованием генерал-фельдмаршала И. И. Дибича над турецкими войсками 30 мая 1829 года в сражении у села Кулевчи.

История службы
Корабль «Кулевчи» был заложен в Николаеве и после спуска на воду в 1847 году вошел в состав Черноморского Флота.

В 1848, 1849 и 1851 годах в составе отрядов выходил в крейсерство у кавказского побережья. В июле—августе 1850 года курсировал вдоль берегов Черного моря по маршруту Севастополь — Феодосия — Керчь — Анапа — Новороссийск — Пицунда — Феодосия — Севастополь под флагом начальника штаба Черноморского Флота контр-адмирала В. А. Корнилова. В составе эскадры находился в практическом плавании в Чёрном море в 1852 году.

С 20 мая по 3 июля 1853 года выходил в крейсерство к проливу Босфор. C августа по сентябрь того же года в составе отряда участвовал в перевозке войск из Одессы в Севастополь.

Участвовал в Крымской войне. 12 ноября 1853 года вышел из Севастополя к Синопу в составе эскадры контр-адмирала Ф. М. Новосильского на усиление эскадры П. С. Нахимова. Через четыре дня эскадры соединились, а ещё через два дня состоялось Синопское сражение.

Во время Синопского сражения совместно с фрегатом «Кагул» дрейфовал в тылу у эскадры для пресечения попыток отхода турецких судов из бухты. Вел обстрел выходящего из бухты турецкого пароход «Таиф», по пароходу было произведено 260 выстрелов, но из-за установившегося встречного ветра фрегат не смог его преследовать, и пароходу удалось уйти. 22 ноября фрегат «Кулевчи» вернулся в Севастополь, совместно с фрегатом «Кагул» сопровождая повреждённый корабль «Императрица Мария».

17 февраля 1854 года вошёл в состав эскадры обороны Севастопольского рейда. 31 марта вместе с фрегатом «Кагул» крейсировал у Севастополя, обнаружил и преследовал английский пароход, подошедший ко входу на рейд. Но пароходу после короткой перестрелки удалось уйти в море. В сентябре 1854 года поставлен в гавань, а экипаж переведён в состав морского батальона.

27 августа 1855 года «Кулевчи» был затоплен на Севастопольском рейде при оставлении города гарнизоном. После войны при расчистке Севастопольской бухты в 25 июня 1859 году был поднят со дна и продан.

Командиры фрегата
Командирами фрегата «Кулевчи» в разное время служили:
 П. И. Кислинский (1848—1849 годы).
 И. А. Ендогуров (1850—1852 годы).
 С. С. Лесовский (по октябрь 1853 года).
 Л. И. Будищев (с октября 1853 года).
 Ф. С. Керн (1854—1855 годы).

Примечания

Литература

Парусные фрегаты Черноморского флота Российской империи
Корабли Крымской войны
Суда по алфавиту

redpajama_set_name: RedPajamaWikipedia


text:
This is a simple program that receives data from WebSocket and dump them onto an LCD screen. It uses the Espressif
ESP31 (ESP32 Beta) module.

# Hardware Wiring

An 128x160 TFT panel based on ILI9163 is needed. It probably works for ST7735 panels but the initial sequence may need
change. Wiring from the TFT panel to ESP31 as follows:
    A0     - GPIO17
    Reset  - GPIO18
    #CS    - GPIO19
    CLK    - GPIO20
    SDI    - GPIO21

# Software setup

ESP32_RTOS_SDK (https://github.com/espressif/ESP32_RTOS_SDK) is used. The steps to setup development environment is fully
detailed in SDK README.

# License/legal

This program uses LCD codes from Sprite_tm's ESP31-SMSEMUhttps://github.com/espressif/esp31-smsemu
The WebSocket server is based on Putilov Andrey 's CWebsocket https://github.com/m8rge/cwebsocket
Both are licensed under MIT license, so does mine.

redpajama_set_name: RedPajamaGithub


text:
#include <scsi/sas.h>
#include <linux/bitops.h>
#include "isci.h"
#include "port.h"
#include "remote_device.h"
#include "request.h"
#include "remote_node_context.h"
#include "scu_event_codes.h"
#include "task.h"

#undef C
#define C(a) (#a)
const char *dev_state_name(enum sci_remote_device_states state)
{
	static const char * const strings[] = REMOTE_DEV_STATES;

	return strings[state];
}
#undef C

enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev,
					  enum sci_remote_node_suspension_reasons reason)
{
	return sci_remote_node_context_suspend(&idev->rnc, reason,
					       SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT);
}

/**
 * isci_remote_device_ready() - This function is called by the ihost when the
 *    remote device is ready. We mark the isci device as ready and signal the
 *    waiting proccess.
 * @ihost: our valid isci_host
 * @idev: remote device
 *
 */
static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote_device *idev)
{
	dev_dbg(&ihost->pdev->dev,
		"%s: idev = %p\n", __func__, idev);

	clear_bit(IDEV_IO_NCQERROR, &idev->flags);
	set_bit(IDEV_IO_READY, &idev->flags);
	if (test_and_clear_bit(IDEV_START_PENDING, &idev->flags))
		wake_up(&ihost->eventq);
}

static enum sci_status sci_remote_device_terminate_req(
	struct isci_host *ihost,
	struct isci_remote_device *idev,
	int check_abort,
	struct isci_request *ireq)
{
	if (!test_bit(IREQ_ACTIVE, &ireq->flags) ||
	    (ireq->target_device != idev) ||
	    (check_abort && !test_bit(IREQ_PENDING_ABORT, &ireq->flags)))
		return SCI_SUCCESS;

	dev_dbg(&ihost->pdev->dev,
		"%s: idev=%p; flags=%lx; req=%p; req target=%p\n",
		__func__, idev, idev->flags, ireq, ireq->target_device);

	set_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags);

	return sci_controller_terminate_request(ihost, idev, ireq);
}

static enum sci_status sci_remote_device_terminate_reqs_checkabort(
	struct isci_remote_device *idev,
	int chk)
{
	struct isci_host *ihost = idev->owning_port->owning_controller;
	enum sci_status status  = SCI_SUCCESS;
	u32 i;

	for (i = 0; i < SCI_MAX_IO_REQUESTS; i++) {
		struct isci_request *ireq = ihost->reqs[i];
		enum sci_status s;

		s = sci_remote_device_terminate_req(ihost, idev, chk, ireq);
		if (s != SCI_SUCCESS)
			status = s;
	}
	return status;
}

static bool isci_compare_suspendcount(
	struct isci_remote_device *idev,
	u32 localcount)
{
	smp_rmb();

	/* Check for a change in the suspend count, or the RNC
	 * being destroyed.
	 */
	return (localcount != idev->rnc.suspend_count)
	    || sci_remote_node_context_is_being_destroyed(&idev->rnc);
}

static bool isci_check_reqterm(
	struct isci_host *ihost,
	struct isci_remote_device *idev,
	struct isci_request *ireq,
	u32 localcount)
{
	unsigned long flags;
	bool res;

	spin_lock_irqsave(&ihost->scic_lock, flags);
	res = isci_compare_suspendcount(idev, localcount)
		&& !test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags);
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

	return res;
}

static bool isci_check_devempty(
	struct isci_host *ihost,
	struct isci_remote_device *idev,
	u32 localcount)
{
	unsigned long flags;
	bool res;

	spin_lock_irqsave(&ihost->scic_lock, flags);
	res = isci_compare_suspendcount(idev, localcount)
		&& idev->started_request_count == 0;
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

	return res;
}

enum sci_status isci_remote_device_terminate_requests(
	struct isci_host *ihost,
	struct isci_remote_device *idev,
	struct isci_request *ireq)
{
	enum sci_status status = SCI_SUCCESS;
	unsigned long flags;
	u32 rnc_suspend_count;

	spin_lock_irqsave(&ihost->scic_lock, flags);

	if (isci_get_device(idev) == NULL) {
		dev_dbg(&ihost->pdev->dev, "%s: failed isci_get_device(idev=%p)\n",
			__func__, idev);
		spin_unlock_irqrestore(&ihost->scic_lock, flags);
		status = SCI_FAILURE;
	} else {
		/* If already suspended, don't wait for another suspension. */
		smp_rmb();
		rnc_suspend_count
			= sci_remote_node_context_is_suspended(&idev->rnc)
				? 0 : idev->rnc.suspend_count;

		dev_dbg(&ihost->pdev->dev,
			"%s: idev=%p, ireq=%p; started_request_count=%d, "
				"rnc_suspend_count=%d, rnc.suspend_count=%d"
				"about to wait\n",
			__func__, idev, ireq, idev->started_request_count,
			rnc_suspend_count, idev->rnc.suspend_count);

		#define MAX_SUSPEND_MSECS 10000
		if (ireq) {
			/* Terminate a specific TC. */
			set_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags);
			sci_remote_device_terminate_req(ihost, idev, 0, ireq);
			spin_unlock_irqrestore(&ihost->scic_lock, flags);
			if (!wait_event_timeout(ihost->eventq,
						isci_check_reqterm(ihost, idev, ireq,
								   rnc_suspend_count),
						msecs_to_jiffies(MAX_SUSPEND_MSECS))) {

				dev_warn(&ihost->pdev->dev, "%s host%d timeout single\n",
					 __func__, ihost->id);
				dev_dbg(&ihost->pdev->dev,
					 "%s: ******* Timeout waiting for "
					 "suspend; idev=%p, current state %s; "
					 "started_request_count=%d, flags=%lx\n\t"
					 "rnc_suspend_count=%d, rnc.suspend_count=%d "
					 "RNC: current state %s, current "
					 "suspend_type %x dest state %d;\n"
					 "ireq=%p, ireq->flags = %lx\n",
					 __func__, idev,
					 dev_state_name(idev->sm.current_state_id),
					 idev->started_request_count, idev->flags,
					 rnc_suspend_count, idev->rnc.suspend_count,
					 rnc_state_name(idev->rnc.sm.current_state_id),
					 idev->rnc.suspend_type,
					 idev->rnc.destination_state,
					 ireq, ireq->flags);
			}
			spin_lock_irqsave(&ihost->scic_lock, flags);
			clear_bit(IREQ_NO_AUTO_FREE_TAG, &ireq->flags);
			if (!test_bit(IREQ_ABORT_PATH_ACTIVE, &ireq->flags))
				isci_free_tag(ihost, ireq->io_tag);
			spin_unlock_irqrestore(&ihost->scic_lock, flags);
		} else {
			/* Terminate all TCs. */
			sci_remote_device_terminate_requests(idev);
			spin_unlock_irqrestore(&ihost->scic_lock, flags);
			if (!wait_event_timeout(ihost->eventq,
						isci_check_devempty(ihost, idev,
								    rnc_suspend_count),
						msecs_to_jiffies(MAX_SUSPEND_MSECS))) {

				dev_warn(&ihost->pdev->dev, "%s host%d timeout all\n",
					 __func__, ihost->id);
				dev_dbg(&ihost->pdev->dev,
					"%s: ******* Timeout waiting for "
					"suspend; idev=%p, current state %s; "
					"started_request_count=%d, flags=%lx\n\t"
					"rnc_suspend_count=%d, "
					"RNC: current state %s, "
					"rnc.suspend_count=%d, current "
					"suspend_type %x dest state %d\n",
					__func__, idev,
					dev_state_name(idev->sm.current_state_id),
					idev->started_request_count, idev->flags,
					rnc_suspend_count,
					rnc_state_name(idev->rnc.sm.current_state_id),
					idev->rnc.suspend_count,
					idev->rnc.suspend_type,
					idev->rnc.destination_state);
			}
		}
		dev_dbg(&ihost->pdev->dev, "%s: idev=%p, wait done\n",
			__func__, idev);
		isci_put_device(idev);
	}
	return status;
}

/**
* isci_remote_device_not_ready() - This function is called by the ihost when
*    the remote device is not ready. We mark the isci device as ready (not
*    "ready_for_io") and signal the waiting proccess.
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device
*
* sci_lock is held on entrance to this function.
*/
static void isci_remote_device_not_ready(struct isci_host *ihost,
					 struct isci_remote_device *idev,
					 u32 reason)
{
	dev_dbg(&ihost->pdev->dev,
		"%s: isci_device = %p; reason = %d\n", __func__, idev, reason);

	switch (reason) {
	case SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED:
		set_bit(IDEV_IO_NCQERROR, &idev->flags);

		/* Suspend the remote device so the I/O can be terminated. */
		sci_remote_device_suspend(idev, SCI_SW_SUSPEND_NORMAL);

		/* Kill all outstanding requests for the device. */
		sci_remote_device_terminate_requests(idev);

		/* Fall through into the default case... */
	default:
		clear_bit(IDEV_IO_READY, &idev->flags);
		break;
	}
}

/* called once the remote node context is ready to be freed.
 * The remote device can now report that its stop operation is complete. none
 */
static void rnc_destruct_done(void *_dev)
{
	struct isci_remote_device *idev = _dev;

	BUG_ON(idev->started_request_count != 0);
	sci_change_state(&idev->sm, SCI_DEV_STOPPED);
}

enum sci_status sci_remote_device_terminate_requests(
	struct isci_remote_device *idev)
{
	return sci_remote_device_terminate_reqs_checkabort(idev, 0);
}

enum sci_status sci_remote_device_stop(struct isci_remote_device *idev,
					u32 timeout)
{
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;

	switch (state) {
	case SCI_DEV_INITIAL:
	case SCI_DEV_FAILED:
	case SCI_DEV_FINAL:
	default:
		dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
			 __func__, dev_state_name(state));
		return SCI_FAILURE_INVALID_STATE;
	case SCI_DEV_STOPPED:
		return SCI_SUCCESS;
	case SCI_DEV_STARTING:
		/* device not started so there had better be no requests */
		BUG_ON(idev->started_request_count != 0);
		sci_remote_node_context_destruct(&idev->rnc,
						      rnc_destruct_done, idev);
		/* Transition to the stopping state and wait for the
		 * remote node to complete being posted and invalidated.
		 */
		sci_change_state(sm, SCI_DEV_STOPPING);
		return SCI_SUCCESS;
	case SCI_DEV_READY:
	case SCI_STP_DEV_IDLE:
	case SCI_STP_DEV_CMD:
	case SCI_STP_DEV_NCQ:
	case SCI_STP_DEV_NCQ_ERROR:
	case SCI_STP_DEV_AWAIT_RESET:
	case SCI_SMP_DEV_IDLE:
	case SCI_SMP_DEV_CMD:
		sci_change_state(sm, SCI_DEV_STOPPING);
		if (idev->started_request_count == 0)
			sci_remote_node_context_destruct(&idev->rnc,
							 rnc_destruct_done,
							 idev);
		else {
			sci_remote_device_suspend(
				idev, SCI_SW_SUSPEND_LINKHANG_DETECT);
			sci_remote_device_terminate_requests(idev);
		}
		return SCI_SUCCESS;
	case SCI_DEV_STOPPING:
		/* All requests should have been terminated, but if there is an
		 * attempt to stop a device already in the stopping state, then
		 * try again to terminate.
		 */
		return sci_remote_device_terminate_requests(idev);
	case SCI_DEV_RESETTING:
		sci_change_state(sm, SCI_DEV_STOPPING);
		return SCI_SUCCESS;
	}
}

enum sci_status sci_remote_device_reset(struct isci_remote_device *idev)
{
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;

	switch (state) {
	case SCI_DEV_INITIAL:
	case SCI_DEV_STOPPED:
	case SCI_DEV_STARTING:
	case SCI_SMP_DEV_IDLE:
	case SCI_SMP_DEV_CMD:
	case SCI_DEV_STOPPING:
	case SCI_DEV_FAILED:
	case SCI_DEV_RESETTING:
	case SCI_DEV_FINAL:
	default:
		dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
			 __func__, dev_state_name(state));
		return SCI_FAILURE_INVALID_STATE;
	case SCI_DEV_READY:
	case SCI_STP_DEV_IDLE:
	case SCI_STP_DEV_CMD:
	case SCI_STP_DEV_NCQ:
	case SCI_STP_DEV_NCQ_ERROR:
	case SCI_STP_DEV_AWAIT_RESET:
		sci_change_state(sm, SCI_DEV_RESETTING);
		return SCI_SUCCESS;
	}
}

enum sci_status sci_remote_device_reset_complete(struct isci_remote_device *idev)
{
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;

	if (state != SCI_DEV_RESETTING) {
		dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
			 __func__, dev_state_name(state));
		return SCI_FAILURE_INVALID_STATE;
	}

	sci_change_state(sm, SCI_DEV_READY);
	return SCI_SUCCESS;
}

enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev,
						     u32 frame_index)
{
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;
	struct isci_host *ihost = idev->owning_port->owning_controller;
	enum sci_status status;

	switch (state) {
	case SCI_DEV_INITIAL:
	case SCI_DEV_STOPPED:
	case SCI_DEV_STARTING:
	case SCI_STP_DEV_IDLE:
	case SCI_SMP_DEV_IDLE:
	case SCI_DEV_FINAL:
	default:
		dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
			 __func__, dev_state_name(state));
		/* Return the frame back to the controller */
		sci_controller_release_frame(ihost, frame_index);
		return SCI_FAILURE_INVALID_STATE;
	case SCI_DEV_READY:
	case SCI_STP_DEV_NCQ_ERROR:
	case SCI_STP_DEV_AWAIT_RESET:
	case SCI_DEV_STOPPING:
	case SCI_DEV_FAILED:
	case SCI_DEV_RESETTING: {
		struct isci_request *ireq;
		struct ssp_frame_hdr hdr;
		void *frame_header;
		ssize_t word_cnt;

		status = sci_unsolicited_frame_control_get_header(&ihost->uf_control,
								       frame_index,
								       &frame_header);
		if (status != SCI_SUCCESS)
			return status;

		word_cnt = sizeof(hdr) / sizeof(u32);
		sci_swab32_cpy(&hdr, frame_header, word_cnt);

		ireq = sci_request_by_tag(ihost, be16_to_cpu(hdr.tag));
		if (ireq && ireq->target_device == idev) {
			/* The IO request is now in charge of releasing the frame */
			status = sci_io_request_frame_handler(ireq, frame_index);
		} else {
			/* We could not map this tag to a valid IO
			 * request Just toss the frame and continue
			 */
			sci_controller_release_frame(ihost, frame_index);
		}
		break;
	}
	case SCI_STP_DEV_NCQ: {
		struct dev_to_host_fis *hdr;

		status = sci_unsolicited_frame_control_get_header(&ihost->uf_control,
								       frame_index,
								       (void **)&hdr);
		if (status != SCI_SUCCESS)
			return status;

		if (hdr->fis_type == FIS_SETDEVBITS &&
		    (hdr->status & ATA_ERR)) {
			idev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;

			/* TODO Check sactive and complete associated IO if any. */
			sci_change_state(sm, SCI_STP_DEV_NCQ_ERROR);
		} else if (hdr->fis_type == FIS_REGD2H &&
			   (hdr->status & ATA_ERR)) {
			/*
			 * Some devices return D2H FIS when an NCQ error is detected.
			 * Treat this like an SDB error FIS ready reason.
			 */
			idev->not_ready_reason = SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
			sci_change_state(&idev->sm, SCI_STP_DEV_NCQ_ERROR);
		} else
			status = SCI_FAILURE;

		sci_controller_release_frame(ihost, frame_index);
		break;
	}
	case SCI_STP_DEV_CMD:
	case SCI_SMP_DEV_CMD:
		/* The device does not process any UF received from the hardware while
		 * in this state.  All unsolicited frames are forwarded to the io request
		 * object.
		 */
		status = sci_io_request_frame_handler(idev->working_request, frame_index);
		break;
	}

	return status;
}

static bool is_remote_device_ready(struct isci_remote_device *idev)
{

	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;

	switch (state) {
	case SCI_DEV_READY:
	case SCI_STP_DEV_IDLE:
	case SCI_STP_DEV_CMD:
	case SCI_STP_DEV_NCQ:
	case SCI_STP_DEV_NCQ_ERROR:
	case SCI_STP_DEV_AWAIT_RESET:
	case SCI_SMP_DEV_IDLE:
	case SCI_SMP_DEV_CMD:
		return true;
	default:
		return false;
	}
}

/*
 * called once the remote node context has transisitioned to a ready
 * state (after suspending RX and/or TX due to early D2H fis)
 */
static void atapi_remote_device_resume_done(void *_dev)
{
	struct isci_remote_device *idev = _dev;
	struct isci_request *ireq = idev->working_request;

	sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
}

enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev,
						     u32 event_code)
{
	enum sci_status status;
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;

	switch (scu_get_event_type(event_code)) {
	case SCU_EVENT_TYPE_RNC_OPS_MISC:
	case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
	case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
		status = sci_remote_node_context_event_handler(&idev->rnc, event_code);
		break;
	case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT:
		if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) {
			status = SCI_SUCCESS;

			/* Suspend the associated RNC */
			sci_remote_device_suspend(idev, SCI_SW_SUSPEND_NORMAL);

			dev_dbg(scirdev_to_dev(idev),
				"%s: device: %p event code: %x: %s\n",
				__func__, idev, event_code,
				is_remote_device_ready(idev)
				? "I_T_Nexus_Timeout event"
				: "I_T_Nexus_Timeout event in wrong state");

			break;
		}
	/* Else, fall through and treat as unhandled... */
	default:
		dev_dbg(scirdev_to_dev(idev),
			"%s: device: %p event code: %x: %s\n",
			__func__, idev, event_code,
			is_remote_device_ready(idev)
			? "unexpected event"
			: "unexpected event in wrong state");
		status = SCI_FAILURE_INVALID_STATE;
		break;
	}

	if (status != SCI_SUCCESS)
		return status;

	/* Decode device-specific states that may require an RNC resume during
	 * normal operation.  When the abort path is active, these resumes are
	 * managed when the abort path exits.
	 */
	if (state == SCI_STP_DEV_ATAPI_ERROR) {
		/* For ATAPI error state resume the RNC right away. */
		if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
		    scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
			return sci_remote_node_context_resume(&idev->rnc,
							      atapi_remote_device_resume_done,
							      idev);
		}
	}

	if (state == SCI_STP_DEV_IDLE) {

		/* We pick up suspension events to handle specifically to this
		 * state. We resume the RNC right away.
		 */
		if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX ||
		    scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX)
			status = sci_remote_node_context_resume(&idev->rnc, NULL, NULL);
	}

	return status;
}

static void sci_remote_device_start_request(struct isci_remote_device *idev,
						 struct isci_request *ireq,
						 enum sci_status status)
{
	struct isci_port *iport = idev->owning_port;

	/* cleanup requests that failed after starting on the port */
	if (status != SCI_SUCCESS)
		sci_port_complete_io(iport, idev, ireq);
	else {
		kref_get(&idev->kref);
		idev->started_request_count++;
	}
}

enum sci_status sci_remote_device_start_io(struct isci_host *ihost,
						struct isci_remote_device *idev,
						struct isci_request *ireq)
{
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;
	struct isci_port *iport = idev->owning_port;
	enum sci_status status;

	switch (state) {
	case SCI_DEV_INITIAL:
	case SCI_DEV_STOPPED:
	case SCI_DEV_STARTING:
	case SCI_STP_DEV_NCQ_ERROR:
	case SCI_DEV_STOPPING:
	case SCI_DEV_FAILED:
	case SCI_DEV_RESETTING:
	case SCI_DEV_FINAL:
	default:
		dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
			 __func__, dev_state_name(state));
		return SCI_FAILURE_INVALID_STATE;
	case SCI_DEV_READY:
		/* attempt to start an io request for this device object. The remote
		 * device object will issue the start request for the io and if
		 * successful it will start the request for the port object then
		 * increment its own request count.
		 */
		status = sci_port_start_io(iport, idev, ireq);
		if (status != SCI_SUCCESS)
			return status;

		status = sci_remote_node_context_start_io(&idev->rnc, ireq);
		if (status != SCI_SUCCESS)
			break;

		status = sci_request_start(ireq);
		break;
	case SCI_STP_DEV_IDLE: {
		/* handle the start io operation for a sata device that is in
		 * the command idle state. - Evalute the type of IO request to
		 * be started - If its an NCQ request change to NCQ substate -
		 * If its any other command change to the CMD substate
		 *
		 * If this is a softreset we may want to have a different
		 * substate.
		 */
		enum sci_remote_device_states new_state;
		struct sas_task *task = isci_request_access_task(ireq);

		status = sci_port_start_io(iport, idev, ireq);
		if (status != SCI_SUCCESS)
			return status;

		status = sci_remote_node_context_start_io(&idev->rnc, ireq);
		if (status != SCI_SUCCESS)
			break;

		status = sci_request_start(ireq);
		if (status != SCI_SUCCESS)
			break;

		if (task->ata_task.use_ncq)
			new_state = SCI_STP_DEV_NCQ;
		else {
			idev->working_request = ireq;
			new_state = SCI_STP_DEV_CMD;
		}
		sci_change_state(sm, new_state);
		break;
	}
	case SCI_STP_DEV_NCQ: {
		struct sas_task *task = isci_request_access_task(ireq);

		if (task->ata_task.use_ncq) {
			status = sci_port_start_io(iport, idev, ireq);
			if (status != SCI_SUCCESS)
				return status;

			status = sci_remote_node_context_start_io(&idev->rnc, ireq);
			if (status != SCI_SUCCESS)
				break;

			status = sci_request_start(ireq);
		} else
			return SCI_FAILURE_INVALID_STATE;
		break;
	}
	case SCI_STP_DEV_AWAIT_RESET:
		return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
	case SCI_SMP_DEV_IDLE:
		status = sci_port_start_io(iport, idev, ireq);
		if (status != SCI_SUCCESS)
			return status;

		status = sci_remote_node_context_start_io(&idev->rnc, ireq);
		if (status != SCI_SUCCESS)
			break;

		status = sci_request_start(ireq);
		if (status != SCI_SUCCESS)
			break;

		idev->working_request = ireq;
		sci_change_state(&idev->sm, SCI_SMP_DEV_CMD);
		break;
	case SCI_STP_DEV_CMD:
	case SCI_SMP_DEV_CMD:
		/* device is already handling a command it can not accept new commands
		 * until this one is complete.
		 */
		return SCI_FAILURE_INVALID_STATE;
	}

	sci_remote_device_start_request(idev, ireq, status);
	return status;
}

static enum sci_status common_complete_io(struct isci_port *iport,
					  struct isci_remote_device *idev,
					  struct isci_request *ireq)
{
	enum sci_status status;

	status = sci_request_complete(ireq);
	if (status != SCI_SUCCESS)
		return status;

	status = sci_port_complete_io(iport, idev, ireq);
	if (status != SCI_SUCCESS)
		return status;

	sci_remote_device_decrement_request_count(idev);
	return status;
}

enum sci_status sci_remote_device_complete_io(struct isci_host *ihost,
						   struct isci_remote_device *idev,
						   struct isci_request *ireq)
{
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;
	struct isci_port *iport = idev->owning_port;
	enum sci_status status;

	switch (state) {
	case SCI_DEV_INITIAL:
	case SCI_DEV_STOPPED:
	case SCI_DEV_STARTING:
	case SCI_STP_DEV_IDLE:
	case SCI_SMP_DEV_IDLE:
	case SCI_DEV_FAILED:
	case SCI_DEV_FINAL:
	default:
		dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
			 __func__, dev_state_name(state));
		return SCI_FAILURE_INVALID_STATE;
	case SCI_DEV_READY:
	case SCI_STP_DEV_AWAIT_RESET:
	case SCI_DEV_RESETTING:
		status = common_complete_io(iport, idev, ireq);
		break;
	case SCI_STP_DEV_CMD:
	case SCI_STP_DEV_NCQ:
	case SCI_STP_DEV_NCQ_ERROR:
	case SCI_STP_DEV_ATAPI_ERROR:
		status = common_complete_io(iport, idev, ireq);
		if (status != SCI_SUCCESS)
			break;

		if (ireq->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) {
			/* This request causes hardware error, device needs to be Lun Reset.
			 * So here we force the state machine to IDLE state so the rest IOs
			 * can reach RNC state handler, these IOs will be completed by RNC with
			 * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE".
			 */
			sci_change_state(sm, SCI_STP_DEV_AWAIT_RESET);
		} else if (idev->started_request_count == 0)
			sci_change_state(sm, SCI_STP_DEV_IDLE);
		break;
	case SCI_SMP_DEV_CMD:
		status = common_complete_io(iport, idev, ireq);
		if (status != SCI_SUCCESS)
			break;
		sci_change_state(sm, SCI_SMP_DEV_IDLE);
		break;
	case SCI_DEV_STOPPING:
		status = common_complete_io(iport, idev, ireq);
		if (status != SCI_SUCCESS)
			break;

		if (idev->started_request_count == 0)
			sci_remote_node_context_destruct(&idev->rnc,
							 rnc_destruct_done,
							 idev);
		break;
	}

	if (status != SCI_SUCCESS)
		dev_err(scirdev_to_dev(idev),
			"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
			"could not complete\n", __func__, iport,
			idev, ireq, status);
	else
		isci_put_device(idev);

	return status;
}

static void sci_remote_device_continue_request(void *dev)
{
	struct isci_remote_device *idev = dev;

	/* we need to check if this request is still valid to continue. */
	if (idev->working_request)
		sci_controller_continue_io(idev->working_request);
}

enum sci_status sci_remote_device_start_task(struct isci_host *ihost,
						  struct isci_remote_device *idev,
						  struct isci_request *ireq)
{
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;
	struct isci_port *iport = idev->owning_port;
	enum sci_status status;

	switch (state) {
	case SCI_DEV_INITIAL:
	case SCI_DEV_STOPPED:
	case SCI_DEV_STARTING:
	case SCI_SMP_DEV_IDLE:
	case SCI_SMP_DEV_CMD:
	case SCI_DEV_STOPPING:
	case SCI_DEV_FAILED:
	case SCI_DEV_RESETTING:
	case SCI_DEV_FINAL:
	default:
		dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
			 __func__, dev_state_name(state));
		return SCI_FAILURE_INVALID_STATE;
	case SCI_STP_DEV_IDLE:
	case SCI_STP_DEV_CMD:
	case SCI_STP_DEV_NCQ:
	case SCI_STP_DEV_NCQ_ERROR:
	case SCI_STP_DEV_AWAIT_RESET:
		status = sci_port_start_io(iport, idev, ireq);
		if (status != SCI_SUCCESS)
			return status;

		status = sci_request_start(ireq);
		if (status != SCI_SUCCESS)
			goto out;

		/* Note: If the remote device state is not IDLE this will
		 * replace the request that probably resulted in the task
		 * management request.
		 */
		idev->working_request = ireq;
		sci_change_state(sm, SCI_STP_DEV_CMD);

		/* The remote node context must cleanup the TCi to NCQ mapping
		 * table.  The only way to do this correctly is to either write
		 * to the TLCR register or to invalidate and repost the RNC. In
		 * either case the remote node context state machine will take
		 * the correct action when the remote node context is suspended
		 * and later resumed.
		 */
		sci_remote_device_suspend(idev,
					  SCI_SW_SUSPEND_LINKHANG_DETECT);

		status = sci_remote_node_context_start_task(&idev->rnc, ireq,
				sci_remote_device_continue_request, idev);

	out:
		sci_remote_device_start_request(idev, ireq, status);
		/* We need to let the controller start request handler know that
		 * it can't post TC yet. We will provide a callback function to
		 * post TC when RNC gets resumed.
		 */
		return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS;
	case SCI_DEV_READY:
		status = sci_port_start_io(iport, idev, ireq);
		if (status != SCI_SUCCESS)
			return status;

		/* Resume the RNC as needed: */
		status = sci_remote_node_context_start_task(&idev->rnc, ireq,
							    NULL, NULL);
		if (status != SCI_SUCCESS)
			break;

		status = sci_request_start(ireq);
		break;
	}
	sci_remote_device_start_request(idev, ireq, status);

	return status;
}

void sci_remote_device_post_request(struct isci_remote_device *idev, u32 request)
{
	struct isci_port *iport = idev->owning_port;
	u32 context;

	context = request |
		  (ISCI_PEG << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
		  (iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) |
		  idev->rnc.remote_node_index;

	sci_controller_post_request(iport->owning_controller, context);
}

/* called once the remote node context has transisitioned to a
 * ready state.  This is the indication that the remote device object can also
 * transition to ready.
 */
static void remote_device_resume_done(void *_dev)
{
	struct isci_remote_device *idev = _dev;

	if (is_remote_device_ready(idev))
		return;

	/* go 'ready' if we are not already in a ready state */
	sci_change_state(&idev->sm, SCI_DEV_READY);
}

static void sci_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev)
{
	struct isci_remote_device *idev = _dev;
	struct isci_host *ihost = idev->owning_port->owning_controller;

	/* For NCQ operation we do not issue a isci_remote_device_not_ready().
	 * As a result, avoid sending the ready notification.
	 */
	if (idev->sm.previous_state_id != SCI_STP_DEV_NCQ)
		isci_remote_device_ready(ihost, idev);
}

static void sci_remote_device_initial_state_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);

	/* Initial state is a transitional state to the stopped state */
	sci_change_state(&idev->sm, SCI_DEV_STOPPED);
}

/**
 * sci_remote_device_destruct() - free remote node context and destruct
 * @remote_device: This parameter specifies the remote device to be destructed.
 *
 * Remote device objects are a limited resource.  As such, they must be
 * protected.  Thus calls to construct and destruct are mutually exclusive and
 * non-reentrant. The return value shall indicate if the device was
 * successfully destructed or if some failure occurred. enum sci_status This value
 * is returned if the device is successfully destructed.
 * SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied
 * device isn't valid (e.g. it's already been destoryed, the handle isn't
 * valid, etc.).
 */
static enum sci_status sci_remote_device_destruct(struct isci_remote_device *idev)
{
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;
	struct isci_host *ihost;

	if (state != SCI_DEV_STOPPED) {
		dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
			 __func__, dev_state_name(state));
		return SCI_FAILURE_INVALID_STATE;
	}

	ihost = idev->owning_port->owning_controller;
	sci_controller_free_remote_node_context(ihost, idev,
						     idev->rnc.remote_node_index);
	idev->rnc.remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
	sci_change_state(sm, SCI_DEV_FINAL);

	return SCI_SUCCESS;
}

/**
 * isci_remote_device_deconstruct() - This function frees an isci_remote_device.
 * @ihost: This parameter specifies the isci host object.
 * @idev: This parameter specifies the remote device to be freed.
 *
 */
static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_remote_device *idev)
{
	dev_dbg(&ihost->pdev->dev,
		"%s: isci_device = %p\n", __func__, idev);

	/* There should not be any outstanding io's. All paths to
	 * here should go through isci_remote_device_nuke_requests.
	 * If we hit this condition, we will need a way to complete
	 * io requests in process */
	BUG_ON(idev->started_request_count > 0);

	sci_remote_device_destruct(idev);
	list_del_init(&idev->node);
	isci_put_device(idev);
}

static void sci_remote_device_stopped_state_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct isci_host *ihost = idev->owning_port->owning_controller;
	u32 prev_state;

	/* If we are entering from the stopping state let the SCI User know that
	 * the stop operation has completed.
	 */
	prev_state = idev->sm.previous_state_id;
	if (prev_state == SCI_DEV_STOPPING)
		isci_remote_device_deconstruct(ihost, idev);

	sci_controller_remote_device_stopped(ihost, idev);
}

static void sci_remote_device_starting_state_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct isci_host *ihost = idev->owning_port->owning_controller;

	isci_remote_device_not_ready(ihost, idev,
				     SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED);
}

static void sci_remote_device_ready_state_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct isci_host *ihost = idev->owning_port->owning_controller;
	struct domain_device *dev = idev->domain_dev;

	if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) {
		sci_change_state(&idev->sm, SCI_STP_DEV_IDLE);
	} else if (dev_is_expander(dev)) {
		sci_change_state(&idev->sm, SCI_SMP_DEV_IDLE);
	} else
		isci_remote_device_ready(ihost, idev);
}

static void sci_remote_device_ready_state_exit(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct domain_device *dev = idev->domain_dev;

	if (dev->dev_type == SAS_END_DEVICE) {
		struct isci_host *ihost = idev->owning_port->owning_controller;

		isci_remote_device_not_ready(ihost, idev,
					     SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED);
	}
}

static void sci_remote_device_resetting_state_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct isci_host *ihost = idev->owning_port->owning_controller;

	dev_dbg(&ihost->pdev->dev,
		"%s: isci_device = %p\n", __func__, idev);

	sci_remote_device_suspend(idev, SCI_SW_SUSPEND_LINKHANG_DETECT);
}

static void sci_remote_device_resetting_state_exit(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct isci_host *ihost = idev->owning_port->owning_controller;

	dev_dbg(&ihost->pdev->dev,
		"%s: isci_device = %p\n", __func__, idev);

	sci_remote_node_context_resume(&idev->rnc, NULL, NULL);
}

static void sci_stp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);

	idev->working_request = NULL;
	if (sci_remote_node_context_is_ready(&idev->rnc)) {
		/*
		 * Since the RNC is ready, it's alright to finish completion
		 * processing (e.g. signal the remote device is ready). */
		sci_stp_remote_device_ready_idle_substate_resume_complete_handler(idev);
	} else {
		sci_remote_node_context_resume(&idev->rnc,
			sci_stp_remote_device_ready_idle_substate_resume_complete_handler,
			idev);
	}
}

static void sci_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct isci_host *ihost = idev->owning_port->owning_controller;

	BUG_ON(idev->working_request == NULL);

	isci_remote_device_not_ready(ihost, idev,
				     SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED);
}

static void sci_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct isci_host *ihost = idev->owning_port->owning_controller;

	if (idev->not_ready_reason == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED)
		isci_remote_device_not_ready(ihost, idev,
					     idev->not_ready_reason);
}

static void sci_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct isci_host *ihost = idev->owning_port->owning_controller;

	isci_remote_device_ready(ihost, idev);
}

static void sci_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);
	struct isci_host *ihost = idev->owning_port->owning_controller;

	BUG_ON(idev->working_request == NULL);

	isci_remote_device_not_ready(ihost, idev,
				     SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED);
}

static void sci_smp_remote_device_ready_cmd_substate_exit(struct sci_base_state_machine *sm)
{
	struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm);

	idev->working_request = NULL;
}

static const struct sci_base_state sci_remote_device_state_table[] = {
	[SCI_DEV_INITIAL] = {
		.enter_state = sci_remote_device_initial_state_enter,
	},
	[SCI_DEV_STOPPED] = {
		.enter_state = sci_remote_device_stopped_state_enter,
	},
	[SCI_DEV_STARTING] = {
		.enter_state = sci_remote_device_starting_state_enter,
	},
	[SCI_DEV_READY] = {
		.enter_state = sci_remote_device_ready_state_enter,
		.exit_state  = sci_remote_device_ready_state_exit
	},
	[SCI_STP_DEV_IDLE] = {
		.enter_state = sci_stp_remote_device_ready_idle_substate_enter,
	},
	[SCI_STP_DEV_CMD] = {
		.enter_state = sci_stp_remote_device_ready_cmd_substate_enter,
	},
	[SCI_STP_DEV_NCQ] = { },
	[SCI_STP_DEV_NCQ_ERROR] = {
		.enter_state = sci_stp_remote_device_ready_ncq_error_substate_enter,
	},
	[SCI_STP_DEV_ATAPI_ERROR] = { },
	[SCI_STP_DEV_AWAIT_RESET] = { },
	[SCI_SMP_DEV_IDLE] = {
		.enter_state = sci_smp_remote_device_ready_idle_substate_enter,
	},
	[SCI_SMP_DEV_CMD] = {
		.enter_state = sci_smp_remote_device_ready_cmd_substate_enter,
		.exit_state  = sci_smp_remote_device_ready_cmd_substate_exit,
	},
	[SCI_DEV_STOPPING] = { },
	[SCI_DEV_FAILED] = { },
	[SCI_DEV_RESETTING] = {
		.enter_state = sci_remote_device_resetting_state_enter,
		.exit_state  = sci_remote_device_resetting_state_exit
	},
	[SCI_DEV_FINAL] = { },
};

/**
 * sci_remote_device_construct() - common construction
 * @sci_port: SAS/SATA port through which this device is accessed.
 * @sci_dev: remote device to construct
 *
 * This routine just performs benign initialization and does not
 * allocate the remote_node_context which is left to
 * sci_remote_device_[de]a_construct().  sci_remote_device_destruct()
 * frees the remote_node_context(s) for the device.
 */
static void sci_remote_device_construct(struct isci_port *iport,
				  struct isci_remote_device *idev)
{
	idev->owning_port = iport;
	idev->started_request_count = 0;

	sci_init_sm(&idev->sm, sci_remote_device_state_table, SCI_DEV_INITIAL);

	sci_remote_node_context_construct(&idev->rnc,
					       SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
}

/**
 * sci_remote_device_da_construct() - construct direct attached device.
 *
 * The information (e.g. IAF, Signature FIS, etc.) necessary to build
 * the device is known to the SCI Core since it is contained in the
 * sci_phy object.  Remote node context(s) is/are a global resource
 * allocated by this routine, freed by sci_remote_device_destruct().
 *
 * Returns:
 * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed.
 * SCI_FAILURE_UNSUPPORTED_PROTOCOL - e.g. sas device attached to
 * sata-only controller instance.
 * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted.
 */
static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
						       struct isci_remote_device *idev)
{
	enum sci_status status;
	struct sci_port_properties properties;

	sci_remote_device_construct(iport, idev);

	sci_port_get_properties(iport, &properties);
	/* Get accurate port width from port's phy mask for a DA device. */
	idev->device_port_width = hweight32(properties.phy_mask);

	status = sci_controller_allocate_remote_node_context(iport->owning_controller,
							     idev,
							     &idev->rnc.remote_node_index);

	if (status != SCI_SUCCESS)
		return status;

	idev->connection_rate = sci_port_get_max_allowed_speed(iport);

	return SCI_SUCCESS;
}

/**
 * sci_remote_device_ea_construct() - construct expander attached device
 *
 * Remote node context(s) is/are a global resource allocated by this
 * routine, freed by sci_remote_device_destruct().
 *
 * Returns:
 * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed.
 * SCI_FAILURE_UNSUPPORTED_PROTOCOL - e.g. sas device attached to
 * sata-only controller instance.
 * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted.
 */
static enum sci_status sci_remote_device_ea_construct(struct isci_port *iport,
						       struct isci_remote_device *idev)
{
	struct domain_device *dev = idev->domain_dev;
	enum sci_status status;

	sci_remote_device_construct(iport, idev);

	status = sci_controller_allocate_remote_node_context(iport->owning_controller,
								  idev,
								  &idev->rnc.remote_node_index);
	if (status != SCI_SUCCESS)
		return status;

	/* For SAS-2 the physical link rate is actually a logical link
	 * rate that incorporates multiplexing.  The SCU doesn't
	 * incorporate multiplexing and for the purposes of the
	 * connection the logical link rate is that same as the
	 * physical.  Furthermore, the SAS-2 and SAS-1.1 fields overlay
	 * one another, so this code works for both situations.
	 */
	idev->connection_rate = min_t(u16, sci_port_get_max_allowed_speed(iport),
					 dev->linkrate);

	/* / @todo Should I assign the port width by reading all of the phys on the port? */
	idev->device_port_width = 1;

	return SCI_SUCCESS;
}

enum sci_status sci_remote_device_resume(
	struct isci_remote_device *idev,
	scics_sds_remote_node_context_callback cb_fn,
	void *cb_p)
{
	enum sci_status status;

	status = sci_remote_node_context_resume(&idev->rnc, cb_fn, cb_p);
	if (status != SCI_SUCCESS)
		dev_dbg(scirdev_to_dev(idev), "%s: failed to resume: %d\n",
			__func__, status);
	return status;
}

static void isci_remote_device_resume_from_abort_complete(void *cbparam)
{
	struct isci_remote_device *idev = cbparam;
	struct isci_host *ihost = idev->owning_port->owning_controller;
	scics_sds_remote_node_context_callback abort_resume_cb =
		idev->abort_resume_cb;

	dev_dbg(scirdev_to_dev(idev), "%s: passing-along resume: %p\n",
		__func__, abort_resume_cb);

	if (abort_resume_cb != NULL) {
		idev->abort_resume_cb = NULL;
		abort_resume_cb(idev->abort_resume_cbparam);
	}
	clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
	wake_up(&ihost->eventq);
}

static bool isci_remote_device_test_resume_done(
	struct isci_host *ihost,
	struct isci_remote_device *idev)
{
	unsigned long flags;
	bool done;

	spin_lock_irqsave(&ihost->scic_lock, flags);
	done = !test_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags)
		|| test_bit(IDEV_STOP_PENDING, &idev->flags)
		|| sci_remote_node_context_is_being_destroyed(&idev->rnc);
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

	return done;
}

void isci_remote_device_wait_for_resume_from_abort(
	struct isci_host *ihost,
	struct isci_remote_device *idev)
{
	dev_dbg(&ihost->pdev->dev, "%s: starting resume wait: %p\n",
		 __func__, idev);

	#define MAX_RESUME_MSECS 10000
	if (!wait_event_timeout(ihost->eventq,
				isci_remote_device_test_resume_done(ihost, idev),
				msecs_to_jiffies(MAX_RESUME_MSECS))) {

		dev_warn(&ihost->pdev->dev, "%s: #### Timeout waiting for "
			 "resume: %p\n", __func__, idev);
	}
	clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);

	dev_dbg(&ihost->pdev->dev, "%s: resume wait done: %p\n",
		 __func__, idev);
}

enum sci_status isci_remote_device_resume_from_abort(
	struct isci_host *ihost,
	struct isci_remote_device *idev)
{
	unsigned long flags;
	enum sci_status status = SCI_SUCCESS;
	int destroyed;

	spin_lock_irqsave(&ihost->scic_lock, flags);
	/* Preserve any current resume callbacks, for instance from other
	 * resumptions.
	 */
	idev->abort_resume_cb = idev->rnc.user_callback;
	idev->abort_resume_cbparam = idev->rnc.user_cookie;
	set_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);
	clear_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags);
	destroyed = sci_remote_node_context_is_being_destroyed(&idev->rnc);
	if (!destroyed)
		status = sci_remote_device_resume(
			idev, isci_remote_device_resume_from_abort_complete,
			idev);
	spin_unlock_irqrestore(&ihost->scic_lock, flags);
	if (!destroyed && (status == SCI_SUCCESS))
		isci_remote_device_wait_for_resume_from_abort(ihost, idev);
	else
		clear_bit(IDEV_ABORT_PATH_RESUME_PENDING, &idev->flags);

	return status;
}

/**
 * sci_remote_device_start() - This method will start the supplied remote
 *    device.  This method enables normal IO requests to flow through to the
 *    remote device.
 * @remote_device: This parameter specifies the device to be started.
 * @timeout: This parameter specifies the number of milliseconds in which the
 *    start operation should complete.
 *
 * An indication of whether the device was successfully started. SCI_SUCCESS
 * This value is returned if the device was successfully started.
 * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start
 * the device when there have been no phys added to it.
 */
static enum sci_status sci_remote_device_start(struct isci_remote_device *idev,
					       u32 timeout)
{
	struct sci_base_state_machine *sm = &idev->sm;
	enum sci_remote_device_states state = sm->current_state_id;
	enum sci_status status;

	if (state != SCI_DEV_STOPPED) {
		dev_warn(scirdev_to_dev(idev), "%s: in wrong state: %s\n",
			 __func__, dev_state_name(state));
		return SCI_FAILURE_INVALID_STATE;
	}

	status = sci_remote_device_resume(idev, remote_device_resume_done,
					  idev);
	if (status != SCI_SUCCESS)
		return status;

	sci_change_state(sm, SCI_DEV_STARTING);

	return SCI_SUCCESS;
}

static enum sci_status isci_remote_device_construct(struct isci_port *iport,
						    struct isci_remote_device *idev)
{
	struct isci_host *ihost = iport->isci_host;
	struct domain_device *dev = idev->domain_dev;
	enum sci_status status;

	if (dev->parent && dev_is_expander(dev->parent))
		status = sci_remote_device_ea_construct(iport, idev);
	else
		status = sci_remote_device_da_construct(iport, idev);

	if (status != SCI_SUCCESS) {
		dev_dbg(&ihost->pdev->dev, "%s: construct failed: %d\n",
			__func__, status);

		return status;
	}

	/* start the device. */
	status = sci_remote_device_start(idev, ISCI_REMOTE_DEVICE_START_TIMEOUT);

	if (status != SCI_SUCCESS)
		dev_warn(&ihost->pdev->dev, "remote device start failed: %d\n",
			 status);

	return status;
}

/**
 * This function builds the isci_remote_device when a libsas dev_found message
 *    is received.
 * @isci_host: This parameter specifies the isci host object.
 * @port: This parameter specifies the isci_port conected to this device.
 *
 * pointer to new isci_remote_device.
 */
static struct isci_remote_device *
isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport)
{
	struct isci_remote_device *idev;
	int i;

	for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
		idev = &ihost->devices[i];
		if (!test_and_set_bit(IDEV_ALLOCATED, &idev->flags))
			break;
	}

	if (i >= SCI_MAX_REMOTE_DEVICES) {
		dev_warn(&ihost->pdev->dev, "%s: failed\n", __func__);
		return NULL;
	}
	if (WARN_ONCE(!list_empty(&idev->node), "found non-idle remote device\n"))
		return NULL;

	return idev;
}

void isci_remote_device_release(struct kref *kref)
{
	struct isci_remote_device *idev = container_of(kref, typeof(*idev), kref);
	struct isci_host *ihost = idev->isci_port->isci_host;

	idev->domain_dev = NULL;
	idev->isci_port = NULL;
	clear_bit(IDEV_START_PENDING, &idev->flags);
	clear_bit(IDEV_STOP_PENDING, &idev->flags);
	clear_bit(IDEV_IO_READY, &idev->flags);
	clear_bit(IDEV_GONE, &idev->flags);
	smp_mb__before_atomic();
	clear_bit(IDEV_ALLOCATED, &idev->flags);
	wake_up(&ihost->eventq);
}

/**
 * isci_remote_device_stop() - This function is called internally to stop the
 *    remote device.
 * @isci_host: This parameter specifies the isci host object.
 * @isci_device: This parameter specifies the remote device.
 *
 * The status of the ihost request to stop.
 */
enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev)
{
	enum sci_status status;
	unsigned long flags;

	dev_dbg(&ihost->pdev->dev,
		"%s: isci_device = %p\n", __func__, idev);

	spin_lock_irqsave(&ihost->scic_lock, flags);
	idev->domain_dev->lldd_dev = NULL; /* disable new lookups */
	set_bit(IDEV_GONE, &idev->flags);

	set_bit(IDEV_STOP_PENDING, &idev->flags);
	status = sci_remote_device_stop(idev, 50);
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

	/* Wait for the stop complete callback. */
	if (WARN_ONCE(status != SCI_SUCCESS, "failed to stop device\n"))
		/* nothing to wait for */;
	else
		wait_for_device_stop(ihost, idev);

	dev_dbg(&ihost->pdev->dev,
		"%s: isci_device = %p, waiting done.\n", __func__, idev);

	return status;
}

/**
 * isci_remote_device_gone() - This function is called by libsas when a domain
 *    device is removed.
 * @domain_device: This parameter specifies the libsas domain device.
 *
 */
void isci_remote_device_gone(struct domain_device *dev)
{
	struct isci_host *ihost = dev_to_ihost(dev);
	struct isci_remote_device *idev = dev->lldd_dev;

	dev_dbg(&ihost->pdev->dev,
		"%s: domain_device = %p, isci_device = %p, isci_port = %p\n",
		__func__, dev, idev, idev->isci_port);

	isci_remote_device_stop(ihost, idev);
}

/**
 * isci_remote_device_found() - This function is called by libsas when a remote
 *    device is discovered. A remote device object is created and started. the
 *    function then sleeps until the sci core device started message is
 *    received.
 * @domain_device: This parameter specifies the libsas domain device.
 *
 * status, zero indicates success.
 */
int isci_remote_device_found(struct domain_device *dev)
{
	struct isci_host *isci_host = dev_to_ihost(dev);
	struct isci_port *isci_port = dev->port->lldd_port;
	struct isci_remote_device *isci_device;
	enum sci_status status;

	dev_dbg(&isci_host->pdev->dev,
		"%s: domain_device = %p\n", __func__, dev);

	if (!isci_port)
		return -ENODEV;

	isci_device = isci_remote_device_alloc(isci_host, isci_port);
	if (!isci_device)
		return -ENODEV;

	kref_init(&isci_device->kref);
	INIT_LIST_HEAD(&isci_device->node);

	spin_lock_irq(&isci_host->scic_lock);
	isci_device->domain_dev = dev;
	isci_device->isci_port = isci_port;
	list_add_tail(&isci_device->node, &isci_port->remote_dev_list);

	set_bit(IDEV_START_PENDING, &isci_device->flags);
	status = isci_remote_device_construct(isci_port, isci_device);

	dev_dbg(&isci_host->pdev->dev,
		"%s: isci_device = %p\n",
		__func__, isci_device);

	if (status == SCI_SUCCESS) {
		/* device came up, advertise it to the world */
		dev->lldd_dev = isci_device;
	} else
		isci_put_device(isci_device);
	spin_unlock_irq(&isci_host->scic_lock);

	/* wait for the device ready callback. */
	wait_for_device_start(isci_host, isci_device);

	return status == SCI_SUCCESS ? 0 : -ENODEV;
}

enum sci_status isci_remote_device_suspend_terminate(
	struct isci_host *ihost,
	struct isci_remote_device *idev,
	struct isci_request *ireq)
{
	unsigned long flags;
	enum sci_status status;

	/* Put the device into suspension. */
	spin_lock_irqsave(&ihost->scic_lock, flags);
	set_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags);
	sci_remote_device_suspend(idev, SCI_SW_SUSPEND_LINKHANG_DETECT);
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

	/* Terminate and wait for the completions. */
	status = isci_remote_device_terminate_requests(ihost, idev, ireq);
	if (status != SCI_SUCCESS)
		dev_dbg(&ihost->pdev->dev,
			"%s: isci_remote_device_terminate_requests(%p) "
				"returned %d!\n",
			__func__, idev, status);

	/* NOTE: RNC resumption is left to the caller! */
	return status;
}

int isci_remote_device_is_safe_to_abort(
	struct isci_remote_device *idev)
{
	return sci_remote_node_context_is_safe_to_abort(&idev->rnc);
}

enum sci_status sci_remote_device_abort_requests_pending_abort(
	struct isci_remote_device *idev)
{
	return sci_remote_device_terminate_reqs_checkabort(idev, 1);
}

enum sci_status isci_remote_device_reset_complete(
	struct isci_host *ihost,
	struct isci_remote_device *idev)
{
	unsigned long flags;
	enum sci_status status;

	spin_lock_irqsave(&ihost->scic_lock, flags);
	status = sci_remote_device_reset_complete(idev);
	spin_unlock_irqrestore(&ihost->scic_lock, flags);

	return status;
}

void isci_dev_set_hang_detection_timeout(
	struct isci_remote_device *idev,
	u32 timeout)
{
	if (dev_is_sata(idev->domain_dev)) {
		if (timeout) {
			if (test_and_set_bit(IDEV_RNC_LLHANG_ENABLED,
					     &idev->flags))
				return;  /* Already enabled. */
		} else if (!test_and_clear_bit(IDEV_RNC_LLHANG_ENABLED,
					       &idev->flags))
			return;  /* Not enabled. */

		sci_port_set_hang_detection_timeout(idev->owning_port,
						    timeout);
	}
}


text:
CRSL welcomes Muslim chaplain
Abe Asher
When Kelly Stone arrived at Macalester in 2014 as the new College Chaplain, she immediately felt a void in the Center for Religious and Spiritual Life. The school did not have a Muslim religious leader.
"Occasionally I'll meet with Brian [Rosenberg, the College President], and last fall I said to Brian, if you had a request from me, it'd be for a Muslim chaplain," Stone said.
Between increasingly vitriolic political rhetoric in the US and terror attacks perpetrated in the name of Islam around the world, 2015 had already been a difficult year for Muslim students, "and it seemed like things just kept getting worse."
In November of last year, the Islamic State claimed responsibility for a series of attacks that killed and injured more than 500 people in and around Paris. Shortly thereafter, the eventual Republican nominee for President Donald Trump called for a ban on all Muslim immigration to the United States.
"Last year was a really painful year globally, both with instances of violence and terrorism being enacted around the world under the name of Islam. It caused a lot of deep personal pain for students, and the political rhetoric has also been part of that," Stone said.
"I felt within myself, even as I was supporting and counseling students, there were limits where I could only empathize and not fully understand what it must be [like] for students to be grappling with the issues they were grappling with," she continued.
That lack of support for Muslim students was apparent to Stone immediately after she arrived at Macalester from Wellesley College just outside of Boston in the fall of 2014.
"I'd come from an institution that had a Muslim chaplain on staff, so I'd seen first hand the value of having that person to support the community through that," Stone said. "I'd been in Boston when the marathon bombing happened, and my school had students on the route."
"It was so abundantly clear to me — and it was clear to me when I arrived at Macalester — that this was such a deep need. I would again and again in meeting with students hear that a Muslim advisor or teacher would be incredibly valuable."
The growth in Islamic influence on college campuses — including the formation of new Islamic studies departments — echoed the similar growth in Jewish studies and the number of Jewish students and professors on college campuses, in the years and decades following the Holocaust and World War II.
Last winter, Stone went ahead with her recommendation. "I prepared a proposal for the position that went to Donna and was sent on to Brian. Donna did some incredible advocacy, and Brian was very supportive."
It was always a straightforward process. "Kelly did the really important work of pushing this through the administration—and this took a great deal of effort," said Barry Cytron, the Associate Chaplain for Jewish Life and a longtime professor at the college.
The Muslim Student Association (MSA) was involved throughout the process. Said MSA President Eman Ahmed, "Kelly really felt like we needed this, and then people supported her idea. It was time for us to have a Muslim chaplain—and it went along well with the current political situation."
The position was approved last spring, with the goal to have a Muslim chaplain in place for the start of this academic year. In the end, Stone said, the best candidate for the job was someone that Macalester was already familiar with: Ailya Vajid.
"Ailya had been doing some part-time work with us in the spring. We did a full search and looked at a broad range of applicants, and Ailya stood out as exceptionally qualified."
Vajid, who graduated from Swarthmore with a degree in Islamic Studies and had been working at her alma mater before her personal life brought her to Minnesota, was all too happy to take the job—despite the fact that her commute to campus is currently an hour-and-a-half.
"What drew me to Macalester was the small liberal arts context. Being at a school that is values- and social justice-driven, with students who really care about what is going on in the world, makes the work really meaningful," Vajid said.
Vajid started at Macalester on August 20. "It's a real delight to have her here," Stone said. "She's an exceptionally kind and gifted person. I really encourage people who want to get to know her to make an appointment and stop in to see her."
One of the goals in hiring Vajid is for her to become one of the faces of Islam on campus. When the school didn't have a Muslim chaplain, Stone said, "It put some of our students in the unfair place of having to be educators for the whole campus community. Women who wore hijabs were told 'Oh, you can explain Islam to me!'"
Said Vajid, "Part of my work is educating the wider campus community and bringing a human face to Islam."
One of the potential added benefits of having a Muslim chaplain is that, according to Vajid, "[a]s soon as a position like this comes in, more [Muslim] students can come [to Macalester], because it's easier for families to send their students knowing that there will be spiritual support."
The focus for now, however, is to support students who are already here—especially in the current global climate surrounding Islam. In that regard, having a Muslim chaplain is unquestionably a benefit.
"Those are layered and complex things to unpack for a student. It feels really important to have a religious leader who comes from that context to help students make sense of those challenges," Stone said.
Vajid agreed. "It's nice for students to be able to come and talk without having to explain their stories and why they see the world the way they do," she said. "I already understand some of those things."
Already, Vajid admits, "I think I've sent out more condolence and sad emails than I thought I would coming into this work." Just two weeks ago, a series of bombings in New York and New Jersey were, allegedly, executed by a Muslim-American.
The general atmosphere of Islamophobia that has colored much of our political discourse in the last two years is being felt as well. "Inevitably, as we get closer and closer to the election, it's going to be felt more and more. It's always in the background. We're always experiencing it," Vajid said.
Vajid splits her time between Macalester and Carleton, who also created a position for a Muslim chaplain earlier this year. "Macalester is not alone," Stone said. "We saw a rise in the creation of Muslim chaplaincies across the country. We were a part of a national trend."
Vajid joins an InterVarsity team that includes Stone, a staff volunteer, and chaplains from the Buddhist, Catholic and Jewish faiths.
Said Cytron, "This is a very complicated time to be a Muslim in America. There is this incredible propensity towards assimilation, and the way you have to look American — whatever that means — in addition to everything else that's going on in the world."
"This [new position] potentially provides a very meaningful and very powerful source of privacy and council for our Muslim community here," Cytron continued.
It's been a success so far. "A lot of people felt like they needed someone to represent them. Since she's been here, she's been a huge help to the community. We always have someone to go and talk to," Ahmed said.
"At a certain level," Stone said, "this is an institutional commitment to supporting the global community that is gathered here. This is one way that we have really invested in supporting our students in new and creative ways."
And though there have already been a fair number of difficult moments, Vajid is off to a good start.
"I love this work. The students here are very thoughtful and reflective, and inspiring to be around. Being with students as they begin to figure out who they are, and discover who they are, that's very exciting to me," she said.
"I can see myself here for a long time."
islam at mac
muslim american
Weyerhauser Chapel
Abe Asher, Former Editor in Chief
Abe Asher (he/him/his) is a senior political science and religious studies major from Portland, Oregon. He is a 2020 graduate of Macalester, and has in...
Sam Lyman • Sep 9, 2019 at 1:42 pm
Oh my goodness! Amazing article dude! Thank you, However I am having issues with your RSS. I don't understand why I can't subscribe to it. Is there anyone else having the same RSS issues? Anyone that knows the answer can you kindly respond? Thanks!!
https://themacweekly.com/71227/news/crsl-welcomes-muslim-chaplain/#comment-133895


An abandoned pit bull mom along with her newborn puppies have found home.
The staff at the Sacramento SPCA arrived the shelter to find a shocking surprise on their doorstep. A pit bull mom was dumped with her 10 newborn puppies. The mother wasn't chained but she didn't choose to leave her puppies rather she stayed protecting them.
However, they all needed care and there was no food or water for the time they stayed there. From her condition, it seemed that the mom gave birth somewhere else and then was dropped at the shelter shortly after.
The shelter took the family but they were worried to find a foster home for such a big family. But things have been good for them, and shortly a foster dad came in excitement to welcome the big family in their new home.
Their foster dad didn't stop snapchatting the adorable family. The pit bull mom is estimated to be a year old and proved to be a sweet furry friend to the shelter staff as well to her foster dad as she allowed anyone to touch her babies without worry.
This sweet mother has got a strong mother instinct towards her babies, she wouldn't leave them alone at night and leave and decided to keep them warm and safe.
The newborn babies are to stay at their new home for foster care for two months until they are old enough to be adopted and leave their mother's side.
This hero foster dad came with great help. He challenged every difficulty in caring for eleven dogs so as not to separate the babies from their mother's side which would have been very serious to their health.
Kudos to the real hero and to the great mom who stayed there for her babies no matter what!
SHARE these puppies great story with your dog lovers friends.


Make your phone ring NOW with qualified P&C buyers - just $0.75 per household*!
*Minimum mailing quantity of 1,000 units.
X-Date Marketing offers you a tested and proven system for generating Home Insurance (Property & Casualty) policy sales. Letters cost just 75¢ per unit, including list, customer suppression, printing, mailing services and Standard Class Postage, with a low 1,000-letter minimum, ($750 for 1,000 letters including postage & list). Try it for yourself, and you can be enjoying new leads in a few short days.
Target the Home Insurance Renewals in Your Community. We find all of the homeowners in your market area with an upcoming home purchase anniversary date. We plan at least one month in advance, so we can target the customer before they renew their current policy.
We can target the exact areas you want to reach. This can be by Zip Code, County, Carrier Route - even a radius around your location. We can also suppress your current customers, as well as undesirable neighborhoods.
Our xDate letter program is strictly month-to-month. You can try it for one month, or set it on 'auto-pilot' and let it keep running. We don't lock you into a long-term contract, and there is no cost or penalty to drop out at any time.
- The dialogue begins; you're talking business!
- Geography. What Zip Codes / Counties?
- Quantity. How many letters?
That's it! We'll respond right away.
Or simply call us at 800-391-1201.