Re: [PATCH V3 4/4] scsi: ufs: Improve UFS fatal error handling

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

 



On 7/19/2013 7:28 PM, Seungwon Jeon wrote:
> On Tue, July 09, 2013, Sujit Reddy Thumma wrote:
>> Error handling in UFS driver is broken and resets the host controller
>> for fatal errors without re-initialization. Correct the fatal error
>> handling sequence according to UFS Host Controller Interface (HCI)
>> v1.1 specification.
>>
>> o Upon determining fatal error condition the host controller may hang
>>    forever until a reset is applied, so just retrying the command doesn't
>>    work without a reset. So, the reset is applied in the driver context
>>    in a separate work and SCSI mid-layer isn't informed until reset is
>>    applied.
>>
>> o Processed requests which are completed without error are reported to
>>    SCSI layer as successful and any pending commands that are not started
>>    yet or are not cause of the error are re-queued into scsi midlayer queue.
>>    For the command that caused error, host controller or device is reset
>>    and DID_ERROR is returned for command retry after applying reset.
>>
>> o SCSI is informed about the expected Unit-Attentioni exception from the
> Attention'i',  typo.
Okay.

> 
>>    device for the immediate command after a reset so that the SCSI layer
>>    take necessary steps to establish communication with the device.
>>
>> Signed-off-by: Sujit Reddy Thumma <sthumma@xxxxxxxxxxxxxx>
>> ---
>>   drivers/scsi/ufs/ufshcd.c |  349 +++++++++++++++++++++++++++++++++++---------
>>   drivers/scsi/ufs/ufshcd.h |    2 +
>>   drivers/scsi/ufs/ufshci.h |   19 ++-
>>   3 files changed, 295 insertions(+), 75 deletions(-)
>>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index b4c9910..2a3874f 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -80,6 +80,14 @@ enum {
>>   	UFSHCD_EH_DEVICE_RESET_PENDING = (1 << 1),
>>   };
>>
>> +/* UFSHCD UIC layer error flags */
>> +enum {
>> +	UFSHCD_UIC_DL_PA_INIT_ERROR = (1 << 0), /* Data link layer error */
>> +	UFSHCD_UIC_NL_ERROR = (1 << 1), /* Network layer error */
>> +	UFSHCD_UIC_TL_ERROR = (1 << 2), /* Transport Layer error */
>> +	UFSHCD_UIC_DME_ERROR = (1 << 3), /* DME error */
>> +};
>> +
>>   /* Interrupt configuration options */
>>   enum {
>>   	UFSHCD_INT_DISABLE,
>> @@ -108,6 +116,7 @@ enum {
>>
>>   static void ufshcd_tmc_handler(struct ufs_hba *hba);
>>   static void ufshcd_async_scan(void *data, async_cookie_t cookie);
>> +static int ufshcd_reset_and_restore(struct ufs_hba *hba);
>>
>>   /*
>>    * ufshcd_wait_for_register - wait for register value to change
>> @@ -1605,9 +1614,6 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
>>   		goto out;
>>   	}
>>
>> -	if (hba->ufshcd_state == UFSHCD_STATE_RESET)
>> -		scsi_unblock_requests(hba->host);
>> -
>>   out:
>>   	return err;
>>   }
>> @@ -1733,66 +1739,6 @@ static int ufshcd_validate_dev_connection(struct ufs_hba *hba)
>>   }
>>
>>   /**
>> - * ufshcd_do_reset - reset the host controller
>> - * @hba: per adapter instance
>> - *
>> - * Returns SUCCESS/FAILED
>> - */
>> -static int ufshcd_do_reset(struct ufs_hba *hba)
>> -{
>> -	struct ufshcd_lrb *lrbp;
>> -	unsigned long flags;
>> -	int tag;
>> -
>> -	/* block commands from midlayer */
>> -	scsi_block_requests(hba->host);
>> -
>> -	spin_lock_irqsave(hba->host->host_lock, flags);
>> -	hba->ufshcd_state = UFSHCD_STATE_RESET;
>> -
>> -	/* send controller to reset state */
>> -	ufshcd_hba_stop(hba);
>> -	spin_unlock_irqrestore(hba->host->host_lock, flags);
>> -
>> -	/* abort outstanding commands */
>> -	for (tag = 0; tag < hba->nutrs; tag++) {
>> -		if (test_bit(tag, &hba->outstanding_reqs)) {
>> -			lrbp = &hba->lrb[tag];
>> -			if (lrbp->cmd) {
>> -				scsi_dma_unmap(lrbp->cmd);
>> -				lrbp->cmd->result = DID_RESET << 16;
>> -				lrbp->cmd->scsi_done(lrbp->cmd);
>> -				lrbp->cmd = NULL;
>> -				clear_bit_unlock(tag, &hba->lrb_in_use);
>> -			}
>> -		}
>> -	}
>> -
>> -	/* complete device management command */
>> -	if (hba->dev_cmd.complete)
>> -		complete(hba->dev_cmd.complete);
>> -
>> -	/* clear outstanding request/task bit maps */
>> -	hba->outstanding_reqs = 0;
>> -	hba->outstanding_tasks = 0;
>> -
>> -	/* Host controller enable */
>> -	if (ufshcd_hba_enable(hba)) {
>> -		dev_err(hba->dev,
>> -			"Reset: Controller initialization failed\n");
>> -		return FAILED;
>> -	}
>> -
>> -	if (ufshcd_link_startup(hba)) {
>> -		dev_err(hba->dev,
>> -			"Reset: Link start-up failed\n");
>> -		return FAILED;
>> -	}
>> -
>> -	return SUCCESS;
>> -}
>> -
>> -/**
>>    * ufshcd_slave_alloc - handle initial SCSI device configurations
>>    * @sdev: pointer to SCSI device
>>    *
>> @@ -1809,6 +1755,9 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
>>   	sdev->use_10_for_ms = 1;
>>   	scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
>>
>> +	/* allow SCSI layer to restart the device in case of errors */
>> +	sdev->allow_restart = 1;
>> +
>>   	/*
>>   	 * Inform SCSI Midlayer that the LUN queue depth is same as the
>>   	 * controller queue depth. If a LUN queue depth is less than the
>> @@ -2013,6 +1962,9 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
>>   	case OCS_ABORTED:
>>   		result |= DID_ABORT << 16;
>>   		break;
>> +	case OCS_INVALID_COMMAND_STATUS:
>> +		result |= DID_REQUEUE << 16;
>> +		break;
>>   	case OCS_INVALID_CMD_TABLE_ATTR:
>>   	case OCS_INVALID_PRDT_ATTR:
>>   	case OCS_MISMATCH_DATA_BUF_SIZE:
>> @@ -2405,42 +2357,295 @@ out:
>>   	return err;
>>   }
>>
>> +static void ufshcd_decide_eh_xfer_req(struct ufs_hba *hba, u32 ocs)
>> +{
>> +	switch (ocs) {
>> +	case OCS_SUCCESS:
>> +	case OCS_INVALID_COMMAND_STATUS:
>> +		break;
>> +	case OCS_MISMATCH_DATA_BUF_SIZE:
>> +	case OCS_MISMATCH_RESP_UPIU_SIZE:
>> +	case OCS_PEER_COMM_FAILURE:
>> +	case OCS_FATAL_ERROR:
>> +	case OCS_ABORTED:
>> +	case OCS_INVALID_CMD_TABLE_ATTR:
>> +	case OCS_INVALID_PRDT_ATTR:
>> +		ufshcd_set_host_reset_pending(hba);
> Should host be reset on ocs error, including below ufshcd_decide_eh_task_req?
> It's just overall command status.

Yes, the error handling section in the UFS 1.1 spec. mentions so.

> 
>> +		break;
>> +	default:
>> +		dev_err(hba->dev, "%s: unknown OCS 0x%x\n",
>> +				__func__, ocs);
>> +		BUG();
>> +	}
>> +}
>> +
>> +static void ufshcd_decide_eh_task_req(struct ufs_hba *hba, u32 ocs)
>> +{
>> +	switch (ocs) {
>> +	case OCS_TMR_SUCCESS:
>> +	case OCS_TMR_INVALID_COMMAND_STATUS:
>> +		break;
>> +	case OCS_TMR_MISMATCH_REQ_SIZE:
>> +	case OCS_TMR_MISMATCH_RESP_SIZE:
>> +	case OCS_TMR_PEER_COMM_FAILURE:
>> +	case OCS_TMR_INVALID_ATTR:
>> +	case OCS_TMR_ABORTED:
>> +	case OCS_TMR_FATAL_ERROR:
>> +		ufshcd_set_host_reset_pending(hba);
>> +		break;
>> +	default:
>> +		dev_err(hba->dev, "%s: uknown TMR OCS 0x%x\n",
>> +				__func__, ocs);
>> +		BUG();
>> +	}
>> +}
>> +
>>   /**
>> - * ufshcd_fatal_err_handler - handle fatal errors
>> + * ufshcd_error_autopsy_transfer_req() - reads OCS field of failed command and
>> + *                          decide error handling
>>    * @hba: per adapter instance
>> + * @err_xfer: bit mask for transfer request errors
>> + *
>> + * Iterate over completed transfer requests and
>> + * set error handling flags.
>> + */
>> +static void
>> +ufshcd_error_autopsy_transfer_req(struct ufs_hba *hba, u32 *err_xfer)
>> +{
>> +	unsigned long completed;
>> +	u32 doorbell;
>> +	int index;
>> +	int ocs;
>> +
>> +	if (!err_xfer)
>> +		goto out;
>> +
>> +	doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
>> +	completed = doorbell ^ (u32)hba->outstanding_reqs;
>> +
>> +	for (index = 0; index < hba->nutrs; index++) {
>> +		if (test_bit(index, &completed)) {
>> +			ocs = ufshcd_get_tr_ocs(&hba->lrb[index]);
>> +			if ((ocs == OCS_SUCCESS) ||
>> +					(ocs == OCS_INVALID_COMMAND_STATUS))
>> +				continue;
>> +
>> +			*err_xfer |= (1 << index);
>> +			ufshcd_decide_eh_xfer_req(hba, ocs);
>> +		}
>> +	}
>> +out:
>> +	return;
>> +}
>> +
>> +/**
>> + * ufshcd_error_autopsy_task_req() - reads OCS field of failed command and
>> + *                          decide error handling
>> + * @hba: per adapter instance
>> + * @err_tm: bit mask for task management errors
>> + *
>> + * Iterate over completed task management requests and
>> + * set error handling flags.
>> + */
>> +static void
>> +ufshcd_error_autopsy_task_req(struct ufs_hba *hba, u32 *err_tm)
>> +{
>> +	unsigned long completed;
>> +	u32 doorbell;
>> +	int index;
>> +	int ocs;
>> +
>> +	if (!err_tm)
>> +		goto out;
>> +
>> +	doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
>> +	completed = doorbell ^ (u32)hba->outstanding_tasks;
>> +
>> +	for (index = 0; index < hba->nutmrs; index++) {
>> +		if (test_bit(index, &completed)) {
>> +			struct utp_task_req_desc *tm_descp;
>> +
>> +			tm_descp = hba->utmrdl_base_addr;
>> +			ocs = ufshcd_get_tmr_ocs(&tm_descp[index]);
>> +			if ((ocs == OCS_TMR_SUCCESS) ||
>> +					(ocs == OCS_TMR_INVALID_COMMAND_STATUS))
>> +				continue;
>> +
>> +			*err_tm |= (1 << index);
>> +			ufshcd_decide_eh_task_req(hba, ocs);
>> +		}
>> +	}
>> +
>> +out:
>> +	return;
>> +}
>> +
>> +/**
>> + * ufshcd_fatal_err_handler - handle fatal errors
>> + * @work: pointer to work structure
>>    */
>>   static void ufshcd_fatal_err_handler(struct work_struct *work)
>>   {
>>   	struct ufs_hba *hba;
>> +	unsigned long flags;
>> +	u32 err_xfer = 0;
>> +	u32 err_tm = 0;
>> +	int err;
>> +
>>   	hba = container_of(work, struct ufs_hba, feh_workq);
>>
>>   	pm_runtime_get_sync(hba->dev);
>> -	/* check if reset is already in progress */
>> -	if (hba->ufshcd_state != UFSHCD_STATE_RESET)
>> -		ufshcd_do_reset(hba);
>> +	spin_lock_irqsave(hba->host->host_lock, flags);
>> +	if (hba->ufshcd_state == UFSHCD_STATE_RESET) {
>> +		/* complete processed requests and exit */
>> +		ufshcd_transfer_req_compl(hba);
>> +		ufshcd_tmc_handler(hba);
>> +		spin_unlock_irqrestore(hba->host->host_lock, flags);
>> +		pm_runtime_put_sync(hba->dev);
>> +		return;
> Host driver is here with finishing 'scsi_block_requests'.
> 'scsi_unblock_requests' can be called somewhere?

No, but it can be possible that SCSI command timeout which triggers
device/host reset and fatal error handler race each other.

> 
>> +	}
>> +
>> +	hba->ufshcd_state = UFSHCD_STATE_RESET;
>> +	ufshcd_error_autopsy_transfer_req(hba, &err_xfer);
>> +	ufshcd_error_autopsy_task_req(hba, &err_tm);
>> +
>> +	/*
>> +	 * Complete successful and pending transfer requests.
>> +	 * DID_REQUEUE is returned for pending requests as they have
>> +	 * nothing to do with error'ed request and SCSI layer should
>> +	 * not treat them as errors and decrement retry count.
>> +	 */
>> +	hba->outstanding_reqs &= ~err_xfer;
>> +	ufshcd_transfer_req_compl(hba);
>> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
>> +	ufshcd_complete_pending_reqs(hba);
>> +	spin_lock_irqsave(hba->host->host_lock, flags);
>> +	hba->outstanding_reqs |= err_xfer;
> Hmm... error handling seems so complicated.
> To simplify it, how about below?
> 
> 1. If requests(transfer or task management) are completed, finish them with success/failure.
This is what we are trying to do above.

> 2. If there are pending requests, abort them.
No, if a fatal error is occurred it is possible that host controller is
freez'ed we are not sure if it can take task management commands and
execute them.

> 3. If fatal error, reset.
> 


>> +
>> +	/* Complete successful and pending task requests */
>> +	hba->outstanding_tasks &= ~err_tm;
>> +	ufshcd_tmc_handler(hba);
>> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
>> +	ufshcd_complete_pending_tasks(hba);
>> +	spin_lock_irqsave(hba->host->host_lock, flags);
>> +
>> +	hba->outstanding_tasks |= err_tm;
>> +
>> +	/*
>> +	 * Controller may generate multiple fatal errors, handle
>> +	 * errors based on severity.
>> +	 * 1) DEVICE_FATAL_ERROR
>> +	 * 2) SYSTEM_BUS/CONTROLLER_FATAL_ERROR
>> +	 * 3) UIC_ERROR
>> +	 */
>> +	if (hba->errors & DEVICE_FATAL_ERROR) {
>> +		/*
>> +		 * Some HBAs may not clear UTRLDBR/UTMRLDBR or update
>> +		 * OCS field on device fatal error.
>> +		 */
>> +		ufshcd_set_host_reset_pending(hba);
> In DEVICE_FATAL_ERROR, ufshcd_device_reset_pending is right?

It looks so, but the spec. mentions to reset the host as well (8.3.6).

> 
>> +	} else if (hba->errors & (SYSTEM_BUS_FATAL_ERROR |
>> +			CONTROLLER_FATAL_ERROR)) {
>> +		/* eh flags should be set in err autopsy based on OCS values */
>> +		if (!hba->eh_flags)
>> +			WARN(1, "%s: fatal error without error handling\n",
>> +				dev_name(hba->dev));
>> +	} else if (hba->errors & UIC_ERROR) {
>> +		if (hba->uic_error & UFSHCD_UIC_DL_PA_INIT_ERROR) {
>> +			/* fatal error - reset controller */
>> +			ufshcd_set_host_reset_pending(hba);
>> +		} else if (hba->uic_error & (UFSHCD_UIC_NL_ERROR |
>> +					UFSHCD_UIC_TL_ERROR |
>> +					UFSHCD_UIC_DME_ERROR)) {
>> +			/* non-fatal, report error to SCSI layer */
>> +			if (!hba->eh_flags) {
>> +				spin_unlock_irqrestore(
>> +						hba->host->host_lock, flags);
>> +				ufshcd_complete_pending_reqs(hba);
>> +				ufshcd_complete_pending_tasks(hba);
>> +				spin_lock_irqsave(hba->host->host_lock, flags);
>> +			}
>> +		}
>> +	}
>> +	spin_unlock_irqrestore(hba->host->host_lock, flags);
>> +
>> +	if (hba->eh_flags) {
>> +		err = ufshcd_reset_and_restore(hba);
>> +		if (err) {
>> +			ufshcd_clear_host_reset_pending(hba);
>> +			ufshcd_clear_device_reset_pending(hba);
>> +			dev_err(hba->dev, "%s: reset and restore failed\n",
>> +					__func__);
>> +			hba->ufshcd_state = UFSHCD_STATE_ERROR;
>> +		}
>> +		/*
>> +		 * Inform scsi mid-layer that we did reset and allow to handle
>> +		 * Unit Attention properly.
>> +		 */
>> +		scsi_report_bus_reset(hba->host, 0);
>> +		hba->errors = 0;
>> +		hba->uic_error = 0;
>> +	}
>> +	scsi_unblock_requests(hba->host);
>>   	pm_runtime_put_sync(hba->dev);
>>   }
>>
>>   /**
>> - * ufshcd_err_handler - Check for fatal errors
>> - * @work: pointer to a work queue structure
>> + * ufshcd_update_uic_error - check and set fatal UIC error flags.
>> + * @hba: per-adapter instance
>>    */
>> -static void ufshcd_err_handler(struct ufs_hba *hba)
>> +static void ufshcd_update_uic_error(struct ufs_hba *hba)
>>   {
>>   	u32 reg;
>>
>> +	/* PA_INIT_ERROR is fatal and needs UIC reset */
>> +	reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER);
>> +	if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
>> +		hba->uic_error |= UFSHCD_UIC_DL_PA_INIT_ERROR;
>> +
>> +	/* UIC NL/TL/DME errors needs software retry */
>> +	reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_NETWORK_LAYER);
>> +	if (reg)
>> +		hba->uic_error |= UFSHCD_UIC_NL_ERROR;
>> +
>> +	reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_TRANSPORT_LAYER);
>> +	if (reg)
>> +		hba->uic_error |= UFSHCD_UIC_TL_ERROR;
>> +
>> +	reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DME);
>> +	if (reg)
>> +		hba->uic_error |= UFSHCD_UIC_DME_ERROR;
> REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER is not handled.

UFS spec. mentions that it is non-fatal error and UIC recovers
by itself and doesn't need software intervention.

> 
>> +
>> +	dev_dbg(hba->dev, "%s: UIC error flags = 0x%08x\n",
>> +			__func__, hba->uic_error);
>> +}
>> +
>> +/**
>> + * ufshcd_err_handler - Check for fatal errors
>> + * @hba: per-adapter instance
>> + */
>> +static void ufshcd_err_handler(struct ufs_hba *hba)
>> +{
>>   	if (hba->errors & INT_FATAL_ERRORS)
>>   		goto fatal_eh;
>>
>>   	if (hba->errors & UIC_ERROR) {
>> -		reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER);
>> -		if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
>> +		hba->uic_error = 0;
>> +		ufshcd_update_uic_error(hba);
>> +		if (hba->uic_error)
> Except UFSHCD_UIC_DL_PA_INIT_ERROR, it's not fatal. Should it go to fatal_eh?

Please see the UIC error handling in ufshcd_fatal_err_handler(), others
need software intervention so I combined it with fatal_eh to complete
the requests and report to SCSI.

> 
> Thanks,
> Seungwon Jeon
> 
>>   			goto fatal_eh;
>>   	}
>> +	/*
>> +	 * Other errors are either non-fatal or completed by the
>> +	 * controller by updating OCS fields with success/failure.
>> +	 */
>>   	return;
>> +
>>   fatal_eh:
>>   	/* handle fatal errors only when link is functional */
>>   	if (hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) {
>> +		/* block commands from midlayer */
>> +		scsi_block_requests(hba->host);
>>   		/* block commands at driver layer until error is handled */
>>   		hba->ufshcd_state = UFSHCD_STATE_ERROR;
>>   		schedule_work(&hba->feh_workq);
>> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
>> index 7fcedd0..4ee4d1a 100644
>> --- a/drivers/scsi/ufs/ufshcd.h
>> +++ b/drivers/scsi/ufs/ufshcd.h
>> @@ -185,6 +185,7 @@ struct ufs_dev_cmd {
>>    * @feh_workq: Work queue for fatal controller error handling
>>    * @eeh_work: Worker to handle exception events
>>    * @errors: HBA errors
>> + * @uic_error: UFS interconnect layer error status
>>    * @dev_cmd: ufs device management command information
>>    * @auto_bkops_enabled: to track whether bkops is enabled in device
>>    */
>> @@ -235,6 +236,7 @@ struct ufs_hba {
>>
>>   	/* HBA Errors */
>>   	u32 errors;
>> +	u32 uic_error;
>>
>>   	/* Device management request data */
>>   	struct ufs_dev_cmd dev_cmd;
>> diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
>> index f1e1b74..36f68ef 100644
>> --- a/drivers/scsi/ufs/ufshci.h
>> +++ b/drivers/scsi/ufs/ufshci.h
>> @@ -264,7 +264,7 @@ enum {
>>   	UTP_DEVICE_TO_HOST	= 0x04000000,
>>   };
>>
>> -/* Overall command status values */
>> +/* Overall command status values for transfer request */
>>   enum {
>>   	OCS_SUCCESS			= 0x0,
>>   	OCS_INVALID_CMD_TABLE_ATTR	= 0x1,
>> @@ -274,8 +274,21 @@ enum {
>>   	OCS_PEER_COMM_FAILURE		= 0x5,
>>   	OCS_ABORTED			= 0x6,
>>   	OCS_FATAL_ERROR			= 0x7,
>> -	OCS_INVALID_COMMAND_STATUS	= 0x0F,
>> -	MASK_OCS			= 0x0F,
>> +	OCS_INVALID_COMMAND_STATUS	= 0xF,
>> +	MASK_OCS			= 0xFF,
>> +};
>> +
>> +/* Overall command status values for task management request */
>> +enum {
>> +	OCS_TMR_SUCCESS			= 0x0,
>> +	OCS_TMR_INVALID_ATTR		= 0x1,
>> +	OCS_TMR_MISMATCH_REQ_SIZE	= 0x2,
>> +	OCS_TMR_MISMATCH_RESP_SIZE	= 0x3,
>> +	OCS_TMR_PEER_COMM_FAILURE	= 0x4,
>> +	OCS_TMR_ABORTED			= 0x5,
>> +	OCS_TMR_FATAL_ERROR		= 0x6,
>> +	OCS_TMR_INVALID_COMMAND_STATUS	= 0xF,
>> +	MASK_OCS_TMR			= 0xFF,
>>   };
>>
>>   /**
>> --
>> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
>> of Code Aurora Forum, hosted by The Linux Foundation.
>>


-- 
Regards,
Sujit
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux