diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 13:43:21 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 13:43:21 -0700 | 
| commit | 06f4e926d256d902dd9a53dcb400fd74974ce087 (patch) | |
| tree | 0b438b67f5f0eff6fd617bc497a9dace6164a488 /drivers/net/wireless/libertas/if_spi.c | |
| parent | 8e7bfcbab3825d1b404d615cb1b54f44ff81f981 (diff) | |
| parent | d93515611bbc70c2fe4db232e5feb448ed8e4cc9 (diff) | |
| download | olio-linux-3.10-06f4e926d256d902dd9a53dcb400fd74974ce087.tar.xz olio-linux-3.10-06f4e926d256d902dd9a53dcb400fd74974ce087.zip  | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1446 commits)
  macvlan: fix panic if lowerdev in a bond
  tg3: Add braces around 5906 workaround.
  tg3: Fix NETIF_F_LOOPBACK error
  macvlan: remove one synchronize_rcu() call
  networking: NET_CLS_ROUTE4 depends on INET
  irda: Fix error propagation in ircomm_lmp_connect_response()
  irda: Kill set but unused variable 'bytes' in irlan_check_command_param()
  irda: Kill set but unused variable 'clen' in ircomm_connect_indication()
  rxrpc: Fix set but unused variable 'usage' in rxrpc_get_transport()
  be2net: Kill set but unused variable 'req' in lancer_fw_download()
  irda: Kill set but unused vars 'saddr' and 'daddr' in irlan_provider_connect_indication()
  atl1c: atl1c_resume() is only used when CONFIG_PM_SLEEP is defined.
  rxrpc: Fix set but unused variable 'usage' in rxrpc_get_peer().
  rxrpc: Kill set but unused variable 'local' in rxrpc_UDP_error_handler()
  rxrpc: Kill set but unused variable 'sp' in rxrpc_process_connection()
  rxrpc: Kill set but unused variable 'sp' in rxrpc_rotate_tx_window()
  pkt_sched: Kill set but unused variable 'protocol' in tc_classify()
  isdn: capi: Use pr_debug() instead of ifdefs.
  tg3: Update version to 3.119
  tg3: Apply rx_discards fix to 5719/5720
  ...
Fix up trivial conflicts in arch/x86/Kconfig and net/mac80211/agg-tx.c
as per Davem.
Diffstat (limited to 'drivers/net/wireless/libertas/if_spi.c')
| -rw-r--r-- | drivers/net/wireless/libertas/if_spi.c | 282 | 
1 files changed, 198 insertions, 84 deletions
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index f6c2cd665f4..463352c890d 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -17,6 +17,8 @@   * (at your option) any later version.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/moduleparam.h>  #include <linux/firmware.h>  #include <linux/jiffies.h> @@ -57,6 +59,7 @@ struct if_spi_card {  	/* Handles all SPI communication (except for FW load) */  	struct workqueue_struct		*workqueue;  	struct work_struct		packet_work; +	struct work_struct		resume_work;  	u8				cmd_buffer[IF_SPI_CMD_BUF_SIZE]; @@ -68,6 +71,9 @@ struct if_spi_card {  	/* Protects cmd_packet_list and data_packet_list */  	spinlock_t			buffer_lock; + +	/* True is card suspended */ +	u8				suspended;  };  static void free_if_spi_card(struct if_spi_card *card) @@ -139,8 +145,10 @@ static void spu_transaction_finish(struct if_spi_card *card)  	card->prev_xfer_time = jiffies;  } -/* Write out a byte buffer to an SPI register, - * using a series of 16-bit transfers. */ +/* + * Write out a byte buffer to an SPI register, + * using a series of 16-bit transfers. + */  static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)  {  	int err = 0; @@ -204,8 +212,10 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)  	struct spi_transfer dummy_trans;  	struct spi_transfer data_trans; -	/* You must take an even number of bytes from the SPU, even if you -	 * don't care about the last one.  */ +	/* +	 * You must take an even number of bytes from the SPU, even if you +	 * don't care about the last one. +	 */  	BUG_ON(len & 0x1);  	spu_transaction_init(card); @@ -254,8 +264,10 @@ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)  	return ret;  } -/* Read 32 bits from an SPI register. - * The low 16 bits are read first. */ +/* + * Read 32 bits from an SPI register. + * The low 16 bits are read first. + */  static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)  {  	__le32 buf; @@ -267,13 +279,15 @@ static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)  	return err;  } -/* Keep reading 16 bits from an SPI register until you get the correct result. +/* + * Keep reading 16 bits from an SPI register until you get the correct result.   *   * If mask = 0, the correct result is any non-zero number.   * If mask != 0, the correct result is any number where   * number & target_mask == target   * - * Returns -ETIMEDOUT if a second passes without the correct result. */ + * Returns -ETIMEDOUT if a second passes without the correct result. + */  static int spu_wait_for_u16(struct if_spi_card *card, u16 reg,  			u16 target_mask, u16 target)  { @@ -293,16 +307,17 @@ static int spu_wait_for_u16(struct if_spi_card *card, u16 reg,  		}  		udelay(100);  		if (time_after(jiffies, timeout)) { -			lbs_pr_err("%s: timeout with val=%02x, " -			       "target_mask=%02x, target=%02x\n", +			pr_err("%s: timeout with val=%02x, target_mask=%02x, target=%02x\n",  			       __func__, val, target_mask, target);  			return -ETIMEDOUT;  		}  	}  } -/* Read 16 bits from an SPI register until you receive a specific value. - * Returns -ETIMEDOUT if a 4 tries pass without success. */ +/* + * Read 16 bits from an SPI register until you receive a specific value. + * Returns -ETIMEDOUT if a 4 tries pass without success. + */  static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target)  {  	int err, try; @@ -324,8 +339,10 @@ static int spu_set_interrupt_mode(struct if_spi_card *card,  {  	int err = 0; -	/* We can suppress a host interrupt by clearing the appropriate -	 * bit in the "host interrupt status mask" register */ +	/* +	 * We can suppress a host interrupt by clearing the appropriate +	 * bit in the "host interrupt status mask" register +	 */  	if (suppress_host_int) {  		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);  		if (err) @@ -341,10 +358,12 @@ static int spu_set_interrupt_mode(struct if_spi_card *card,  			return err;  	} -	/* If auto-interrupts are on, the completion of certain transactions +	/* +	 * If auto-interrupts are on, the completion of certain transactions  	 * will trigger an interrupt automatically. If auto-interrupts  	 * are off, we need to set the "Card Interrupt Cause" register to -	 * trigger a card interrupt. */ +	 * trigger a card interrupt. +	 */  	if (auto_int) {  		err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG,  				IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO | @@ -387,7 +406,7 @@ static int spu_set_bus_mode(struct if_spi_card *card, u16 mode)  	if (err)  		return err;  	if ((rval & 0xF) != mode) { -		lbs_pr_err("Can't read bus mode register.\n"); +		pr_err("Can't read bus mode register\n");  		return -EIO;  	}  	return 0; @@ -398,8 +417,10 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes)  	int err = 0;  	u32 delay; -	/* We have to start up in timed delay mode so that we can safely -	 * read the Delay Read Register. */ +	/* +	 * We have to start up in timed delay mode so that we can safely +	 * read the Delay Read Register. +	 */  	card->use_dummy_writes = 0;  	err = spu_set_bus_mode(card,  				IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | @@ -455,8 +476,10 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,  	/* Load helper firmware image */  	while (bytes_remaining > 0) { -		/* Scratch pad 1 should contain the number of bytes we -		 * want to download to the firmware */ +		/* +		 * Scratch pad 1 should contain the number of bytes we +		 * want to download to the firmware +		 */  		err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,  					HELPER_FW_LOAD_CHUNK_SZ);  		if (err) @@ -468,8 +491,10 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,  		if (err)  			goto out; -		/* Feed the data into the command read/write port reg -		 * in chunks of 64 bytes */ +		/* +		 * Feed the data into the command read/write port reg +		 * in chunks of 64 bytes +		 */  		memset(temp, 0, sizeof(temp));  		memcpy(temp, fw,  		       min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ)); @@ -491,9 +516,11 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,  		fw += HELPER_FW_LOAD_CHUNK_SZ;  	} -	/* Once the helper / single stage firmware download is complete, +	/* +	 * Once the helper / single stage firmware download is complete,  	 * write 0 to scratch pad 1 and interrupt the -	 * bootloader. This completes the helper download. */ +	 * bootloader. This completes the helper download. +	 */  	err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);  	if (err)  		goto out; @@ -508,26 +535,30 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,  out:  	if (err) -		lbs_pr_err("failed to load helper firmware (err=%d)\n", err); +		pr_err("failed to load helper firmware (err=%d)\n", err);  	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);  	return err;  } -/* Returns the length of the next packet the firmware expects us to send - * Sets crc_err if the previous transfer had a CRC error. */ +/* + * Returns the length of the next packet the firmware expects us to send. + * Sets crc_err if the previous transfer had a CRC error. + */  static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,  						int *crc_err)  {  	u16 len;  	int err = 0; -	/* wait until the host interrupt status register indicates -	 * that we are ready to download */ +	/* +	 * wait until the host interrupt status register indicates +	 * that we are ready to download +	 */  	err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,  				IF_SPI_HIST_CMD_DOWNLOAD_RDY,  				IF_SPI_HIST_CMD_DOWNLOAD_RDY);  	if (err) { -		lbs_pr_err("timed out waiting for host_int_status\n"); +		pr_err("timed out waiting for host_int_status\n");  		return err;  	} @@ -537,9 +568,8 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,  		return err;  	if (len > IF_SPI_CMD_BUF_SIZE) { -		lbs_pr_err("firmware load device requested a larger " -			   "tranfer than we are prepared to " -			   "handle. (len = %d)\n", len); +		pr_err("firmware load device requested a larger transfer than we are prepared to handle (len = %d)\n", +		       len);  		return -EIO;  	}  	if (len & 0x1) { @@ -555,6 +585,7 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,  static int if_spi_prog_main_firmware(struct if_spi_card *card,  					const struct firmware *firmware)  { +	struct lbs_private *priv = card->priv;  	int len, prev_len;  	int bytes, crc_err = 0, err = 0;  	const u8 *fw; @@ -568,8 +599,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,  	err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);  	if (err) { -		lbs_pr_err("%s: timed out waiting for initial " -			   "scratch reg = 0\n", __func__); +		netdev_err(priv->dev, +			   "%s: timed out waiting for initial scratch reg = 0\n", +			   __func__);  		goto out;  	} @@ -583,17 +615,18 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,  			goto out;  		}  		if (bytes < 0) { -			/* If there are no more bytes left, we would normally -			 * expect to have terminated with len = 0 */ -			lbs_pr_err("Firmware load wants more bytes " -				   "than we have to offer.\n"); +			/* +			 * If there are no more bytes left, we would normally +			 * expect to have terminated with len = 0 +			 */ +			netdev_err(priv->dev, +				   "Firmware load wants more bytes than we have to offer.\n");  			break;  		}  		if (crc_err) {  			/* Previous transfer failed. */  			if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) { -				lbs_pr_err("Too many CRC errors encountered " -					   "in firmware load.\n"); +				pr_err("Too many CRC errors encountered in firmware load.\n");  				err = -EIO;  				goto out;  			} @@ -622,21 +655,20 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card,  		prev_len = len;  	}  	if (bytes > prev_len) { -		lbs_pr_err("firmware load wants fewer bytes than " -			   "we have to offer.\n"); +		pr_err("firmware load wants fewer bytes than we have to offer\n");  	}  	/* Confirm firmware download */  	err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG,  					SUCCESSFUL_FW_DOWNLOAD_MAGIC);  	if (err) { -		lbs_pr_err("failed to confirm the firmware download\n"); +		pr_err("failed to confirm the firmware download\n");  		goto out;  	}  out:  	if (err) -		lbs_pr_err("failed to load firmware (err=%d)\n", err); +		pr_err("failed to load firmware (err=%d)\n", err);  	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);  	return err;  } @@ -656,14 +688,18 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)  	u16 len;  	u8 i; -	/* We need a buffer big enough to handle whatever people send to -	 * hw_host_to_card */ +	/* +	 * We need a buffer big enough to handle whatever people send to +	 * hw_host_to_card +	 */  	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE);  	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE); -	/* It's just annoying if the buffer size isn't a multiple of 4, because -	 * then we might have len <  IF_SPI_CMD_BUF_SIZE but -	 * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */ +	/* +	 * It's just annoying if the buffer size isn't a multiple of 4, because +	 * then we might have len < IF_SPI_CMD_BUF_SIZE but +	 * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE +	 */  	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0);  	lbs_deb_enter(LBS_DEB_SPI); @@ -673,13 +709,13 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)  	if (err)  		goto out;  	if (!len) { -		lbs_pr_err("%s: error: card has no data for host\n", +		netdev_err(priv->dev, "%s: error: card has no data for host\n",  			   __func__);  		err = -EINVAL;  		goto out;  	} else if (len > IF_SPI_CMD_BUF_SIZE) { -		lbs_pr_err("%s: error: response packet too large: " -			   "%d bytes, but maximum is %d\n", +		netdev_err(priv->dev, +			   "%s: error: response packet too large: %d bytes, but maximum is %d\n",  			   __func__, len, IF_SPI_CMD_BUF_SIZE);  		err = -EINVAL;  		goto out; @@ -701,7 +737,7 @@ static int if_spi_c2h_cmd(struct if_spi_card *card)  out:  	if (err) -		lbs_pr_err("%s: err=%d\n", __func__, err); +		netdev_err(priv->dev, "%s: err=%d\n", __func__, err);  	lbs_deb_leave(LBS_DEB_SPI);  	return err;  } @@ -709,6 +745,7 @@ out:  /* Move data from the card to the host */  static int if_spi_c2h_data(struct if_spi_card *card)  { +	struct lbs_private *priv = card->priv;  	struct sk_buff *skb;  	char *data;  	u16 len; @@ -721,13 +758,13 @@ static int if_spi_c2h_data(struct if_spi_card *card)  	if (err)  		goto out;  	if (!len) { -		lbs_pr_err("%s: error: card has no data for host\n", +		netdev_err(priv->dev, "%s: error: card has no data for host\n",  			   __func__);  		err = -EINVAL;  		goto out;  	} else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { -		lbs_pr_err("%s: error: card has %d bytes of data, but " -			   "our maximum skb size is %zu\n", +		netdev_err(priv->dev, +			   "%s: error: card has %d bytes of data, but our maximum skb size is %zu\n",  			   __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);  		err = -EINVAL;  		goto out; @@ -759,7 +796,7 @@ free_skb:  	dev_kfree_skb(skb);  out:  	if (err) -		lbs_pr_err("%s: err=%d\n", __func__, err); +		netdev_err(priv->dev, "%s: err=%d\n", __func__, err);  	lbs_deb_leave(LBS_DEB_SPI);  	return err;  } @@ -768,6 +805,7 @@ out:  static void if_spi_h2c(struct if_spi_card *card,  			struct if_spi_packet *packet, int type)  { +	struct lbs_private *priv = card->priv;  	int err = 0;  	u16 int_type, port_reg; @@ -781,7 +819,8 @@ static void if_spi_h2c(struct if_spi_card *card,  		port_reg = IF_SPI_CMD_RDWRPORT_REG;  		break;  	default: -		lbs_pr_err("can't transfer buffer of type %d\n", type); +		netdev_err(priv->dev, "can't transfer buffer of type %d\n", +			   type);  		err = -EINVAL;  		goto out;  	} @@ -795,7 +834,7 @@ out:  	kfree(packet);  	if (err) -		lbs_pr_err("%s: error %d\n", __func__, err); +		netdev_err(priv->dev, "%s: error %d\n", __func__, err);  }  /* Inform the host about a card event */ @@ -819,7 +858,7 @@ static void if_spi_e2h(struct if_spi_card *card)  	lbs_queue_event(priv, cause & 0xff);  out:  	if (err) -		lbs_pr_err("%s: error %d\n", __func__, err); +		netdev_err(priv->dev, "%s: error %d\n", __func__, err);  }  static void if_spi_host_to_card_worker(struct work_struct *work) @@ -829,17 +868,21 @@ static void if_spi_host_to_card_worker(struct work_struct *work)  	u16 hiStatus;  	unsigned long flags;  	struct if_spi_packet *packet; +	struct lbs_private *priv;  	card = container_of(work, struct if_spi_card, packet_work); +	priv = card->priv;  	lbs_deb_enter(LBS_DEB_SPI); -	/* Read the host interrupt status register to see what we -	 * can do. */ +	/* +	 * Read the host interrupt status register to see what we +	 * can do. +	 */  	err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,  				&hiStatus);  	if (err) { -		lbs_pr_err("I/O error\n"); +		netdev_err(priv->dev, "I/O error\n");  		goto err;  	} @@ -854,12 +897,15 @@ static void if_spi_host_to_card_worker(struct work_struct *work)  			goto err;  	} -	/* workaround: in PS mode, the card does not set the Command -	 * Download Ready bit, but it sets TX Download Ready. */ +	/* +	 * workaround: in PS mode, the card does not set the Command +	 * Download Ready bit, but it sets TX Download Ready. +	 */  	if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||  	   (card->priv->psstate != PS_STATE_FULL_POWER &&  	    (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { -		/* This means two things. First of all, +		/* +		 * This means two things. First of all,  		 * if there was a previous command sent, the card has  		 * successfully received it.  		 * Secondly, it is now ready to download another @@ -867,8 +913,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work)  		 */  		lbs_host_to_card_done(card->priv); -		/* Do we have any command packets from the host to -		 * send? */ +		/* Do we have any command packets from the host to send? */  		packet = NULL;  		spin_lock_irqsave(&card->buffer_lock, flags);  		if (!list_empty(&card->cmd_packet_list)) { @@ -882,8 +927,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work)  			if_spi_h2c(card, packet, MVMS_CMD);  	}  	if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { -		/* Do we have any data packets from the host to -		 * send? */ +		/* Do we have any data packets from the host to send? */  		packet = NULL;  		spin_lock_irqsave(&card->buffer_lock, flags);  		if (!list_empty(&card->data_packet_list)) { @@ -901,7 +945,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work)  err:  	if (err) -		lbs_pr_err("%s: got error %d\n", __func__, err); +		netdev_err(priv->dev, "%s: got error %d\n", __func__, err);  	lbs_deb_leave(LBS_DEB_SPI);  } @@ -910,7 +954,8 @@ err:   * Host to Card   *   * Called from Libertas to transfer some data to the WLAN device - * We can't sleep here. */ + * We can't sleep here. + */  static int if_spi_host_to_card(struct lbs_private *priv,  				u8 type, u8 *buf, u16 nb)  { @@ -923,7 +968,8 @@ static int if_spi_host_to_card(struct lbs_private *priv,  	lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);  	if (nb == 0) { -		lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb); +		netdev_err(priv->dev, "%s: invalid size requested: %d\n", +			   __func__, nb);  		err = -EINVAL;  		goto out;  	} @@ -951,7 +997,8 @@ static int if_spi_host_to_card(struct lbs_private *priv,  		spin_unlock_irqrestore(&card->buffer_lock, flags);  		break;  	default: -		lbs_pr_err("can't transfer buffer of type %d", type); +		netdev_err(priv->dev, "can't transfer buffer of type %d\n", +			   type);  		err = -EINVAL;  		break;  	} @@ -984,6 +1031,7 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)  static int if_spi_init_card(struct if_spi_card *card)  { +	struct lbs_private *priv = card->priv;  	struct spi_device *spi = card->spi;  	int err, i;  	u32 scratch; @@ -1012,8 +1060,8 @@ static int if_spi_init_card(struct if_spi_card *card)  				break;  		}  		if (i == ARRAY_SIZE(fw_table)) { -			lbs_pr_err("Unsupported chip_id: 0x%02x\n", -					card->card_id); +			netdev_err(priv->dev, "Unsupported chip_id: 0x%02x\n", +				   card->card_id);  			err = -ENODEV;  			goto out;  		} @@ -1022,7 +1070,8 @@ static int if_spi_init_card(struct if_spi_card *card)  					card->card_id, &fw_table[0], &helper,  					&mainfw);  		if (err) { -			lbs_pr_err("failed to find firmware (%d)\n", err); +			netdev_err(priv->dev, "failed to find firmware (%d)\n", +				   err);  			goto out;  		} @@ -1057,6 +1106,28 @@ out:  	return err;  } +static void if_spi_resume_worker(struct work_struct *work) +{ +	struct if_spi_card *card; + +	card = container_of(work, struct if_spi_card, resume_work); + +	if (card->suspended) { +		if (card->pdata->setup) +			card->pdata->setup(card->spi); + +		/* Init card ... */ +		if_spi_init_card(card); + +		enable_irq(card->spi->irq); + +		/* And resume it ... */ +		lbs_resume(card->priv); + +		card->suspended = 0; +	} +} +  static int __devinit if_spi_probe(struct spi_device *spi)  {  	struct if_spi_card *card; @@ -1099,14 +1170,17 @@ static int __devinit if_spi_probe(struct spi_device *spi)  	if (err)  		goto free_card; -	/* Register our card with libertas. -	 * This will call alloc_etherdev */ +	/* +	 * Register our card with libertas. +	 * This will call alloc_etherdev. +	 */  	priv = lbs_add_card(card, &spi->dev);  	if (!priv) {  		err = -ENOMEM;  		goto free_card;  	}  	card->priv = priv; +	priv->setup_fw_on_resume = 1;  	priv->card = card;  	priv->hw_host_to_card = if_spi_host_to_card;  	priv->enter_deep_sleep = NULL; @@ -1117,17 +1191,20 @@ static int __devinit if_spi_probe(struct spi_device *spi)  	/* Initialize interrupt handling stuff. */  	card->workqueue = create_workqueue("libertas_spi");  	INIT_WORK(&card->packet_work, if_spi_host_to_card_worker); +	INIT_WORK(&card->resume_work, if_spi_resume_worker);  	err = request_irq(spi->irq, if_spi_host_interrupt,  			IRQF_TRIGGER_FALLING, "libertas_spi", card);  	if (err) { -		lbs_pr_err("can't get host irq line-- request_irq failed\n"); +		pr_err("can't get host irq line-- request_irq failed\n");  		goto terminate_workqueue;  	} -	/* Start the card. +	/* +	 * Start the card.  	 * This will call register_netdev, and we'll start -	 * getting interrupts... */ +	 * getting interrupts... +	 */  	err = lbs_start_card(priv);  	if (err)  		goto release_irq; @@ -1161,6 +1238,8 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)  	lbs_deb_spi("libertas_spi_remove\n");  	lbs_deb_enter(LBS_DEB_SPI); +	cancel_work_sync(&card->resume_work); +  	lbs_stop_card(priv);  	lbs_remove_card(priv); /* will call free_netdev */ @@ -1174,6 +1253,40 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)  	return 0;  } +static int if_spi_suspend(struct device *dev) +{ +	struct spi_device *spi = to_spi_device(dev); +	struct if_spi_card *card = spi_get_drvdata(spi); + +	if (!card->suspended) { +		lbs_suspend(card->priv); +		flush_workqueue(card->workqueue); +		disable_irq(spi->irq); + +		if (card->pdata->teardown) +			card->pdata->teardown(spi); +		card->suspended = 1; +	} + +	return 0; +} + +static int if_spi_resume(struct device *dev) +{ +	struct spi_device *spi = to_spi_device(dev); +	struct if_spi_card *card = spi_get_drvdata(spi); + +	/* Schedule delayed work */ +	schedule_work(&card->resume_work); + +	return 0; +} + +static const struct dev_pm_ops if_spi_pm_ops = { +	.suspend	= if_spi_suspend, +	.resume		= if_spi_resume, +}; +  static struct spi_driver libertas_spi_driver = {  	.probe	= if_spi_probe,  	.remove = __devexit_p(libertas_spi_remove), @@ -1181,6 +1294,7 @@ static struct spi_driver libertas_spi_driver = {  		.name	= "libertas_spi",  		.bus	= &spi_bus_type,  		.owner	= THIS_MODULE, +		.pm	= &if_spi_pm_ops,  	},  };  |