diff options
Diffstat (limited to 'drivers/net/wireless/iwlegacy/3945-mac.c')
| -rw-r--r-- | drivers/net/wireless/iwlegacy/3945-mac.c | 98 | 
1 files changed, 60 insertions, 38 deletions
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index d604b4036a7..3630a41df50 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -572,26 +572,11 @@ il3945_tx_skb(struct il_priv *il,  	il3945_hw_build_tx_cmd_rate(il, out_cmd, info, hdr, sta_id);  	/* Total # bytes to be transmitted */ -	len = (u16) skb->len; -	tx_cmd->len = cpu_to_le16(len); +	tx_cmd->len = cpu_to_le16((u16) skb->len); -	il_update_stats(il, true, fc, len);  	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;  	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; -	if (!ieee80211_has_morefrags(hdr->frame_control)) { -		txq->need_update = 1; -	} else { -		wait_write_ptr = 1; -		txq->need_update = 0; -	} - -	D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence)); -	D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); -	il_print_hex_dump(il, IL_DL_TX, tx_cmd, sizeof(*tx_cmd)); -	il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd->hdr, -			  ieee80211_hdrlen(fc)); -  	/*  	 * Use the first empty entry in this queue's command buffer array  	 * to contain the Tx command and MAC header concatenated together @@ -610,14 +595,8 @@ il3945_tx_skb(struct il_priv *il,  	 * within command buffer array. */  	txcmd_phys =  	    pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE); -	/* we do not map meta data ... so we can safely access address to -	 * provide to unmap command*/ -	dma_unmap_addr_set(out_meta, mapping, txcmd_phys); -	dma_unmap_len_set(out_meta, len, len); - -	/* Add buffer containing Tx command and MAC(!) header to TFD's -	 * first entry */ -	il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); +	if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys))) +		goto drop_unlock;  	/* Set up TFD's 2nd entry to point directly to remainder of skb,  	 * if any (802.11 null frames have no payload). */ @@ -626,10 +605,34 @@ il3945_tx_skb(struct il_priv *il,  		phys_addr =  		    pci_map_single(il->pci_dev, skb->data + hdr_len, len,  				   PCI_DMA_TODEVICE); +		if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr))) +			goto drop_unlock; +	} + +	/* Add buffer containing Tx command and MAC(!) header to TFD's +	 * first entry */ +	il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); +	dma_unmap_addr_set(out_meta, mapping, txcmd_phys); +	dma_unmap_len_set(out_meta, len, len); +	if (len)  		il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0,  					       U32_PAD(len)); + +	if (!ieee80211_has_morefrags(hdr->frame_control)) { +		txq->need_update = 1; +	} else { +		wait_write_ptr = 1; +		txq->need_update = 0;  	} +	il_update_stats(il, true, fc, skb->len); + +	D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence)); +	D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); +	il_print_hex_dump(il, IL_DL_TX, tx_cmd, sizeof(*tx_cmd)); +	il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd->hdr, +			  ieee80211_hdrlen(fc)); +  	/* Tell device the write idx *just past* this latest filled TFD */  	q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);  	il_txq_update_write_ptr(il, txq); @@ -1001,12 +1004,12 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)  	struct list_head *element;  	struct il_rx_buf *rxb;  	struct page *page; +	dma_addr_t page_dma;  	unsigned long flags;  	gfp_t gfp_mask = priority;  	while (1) {  		spin_lock_irqsave(&rxq->lock, flags); -  		if (list_empty(&rxq->rx_used)) {  			spin_unlock_irqrestore(&rxq->lock, flags);  			return; @@ -1035,26 +1038,34 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)  			break;  		} +		/* Get physical address of RB/SKB */ +		page_dma = +		    pci_map_page(il->pci_dev, page, 0, +				 PAGE_SIZE << il->hw_params.rx_page_order, +				 PCI_DMA_FROMDEVICE); + +		if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) { +			__free_pages(page, il->hw_params.rx_page_order); +			break; +		} +  		spin_lock_irqsave(&rxq->lock, flags); +  		if (list_empty(&rxq->rx_used)) {  			spin_unlock_irqrestore(&rxq->lock, flags); +			pci_unmap_page(il->pci_dev, page_dma, +				       PAGE_SIZE << il->hw_params.rx_page_order, +				       PCI_DMA_FROMDEVICE);  			__free_pages(page, il->hw_params.rx_page_order);  			return;  		} +  		element = rxq->rx_used.next;  		rxb = list_entry(element, struct il_rx_buf, list);  		list_del(element); -		spin_unlock_irqrestore(&rxq->lock, flags);  		rxb->page = page; -		/* Get physical address of RB/SKB */ -		rxb->page_dma = -		    pci_map_page(il->pci_dev, page, 0, -				 PAGE_SIZE << il->hw_params.rx_page_order, -				 PCI_DMA_FROMDEVICE); - -		spin_lock_irqsave(&rxq->lock, flags); - +		rxb->page_dma = page_dma;  		list_add_tail(&rxb->list, &rxq->rx_free);  		rxq->free_count++;  		il->alloc_rxb_page++; @@ -1284,8 +1295,15 @@ il3945_rx_handle(struct il_priv *il)  			    pci_map_page(il->pci_dev, rxb->page, 0,  					 PAGE_SIZE << il->hw_params.  					 rx_page_order, PCI_DMA_FROMDEVICE); -			list_add_tail(&rxb->list, &rxq->rx_free); -			rxq->free_count++; +			if (unlikely(pci_dma_mapping_error(il->pci_dev, +							   rxb->page_dma))) { +				__il_free_pages(il, rxb->page); +				rxb->page = NULL; +				list_add_tail(&rxb->list, &rxq->rx_used); +			} else { +				list_add_tail(&rxb->list, &rxq->rx_free); +				rxq->free_count++; +			}  		} else  			list_add_tail(&rxb->list, &rxq->rx_used); @@ -3273,7 +3291,7 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr,  	if (count) {  		char *p = buffer; -		strncpy(buffer, buf, min(sizeof(buffer), count)); +		strlcpy(buffer, buf, sizeof(buffer));  		channel = simple_strtoul(p, NULL, 0);  		if (channel)  			params.channel = channel; @@ -3474,6 +3492,7 @@ struct ieee80211_ops il3945_mac_ops = {  	.sta_add = il3945_mac_sta_add,  	.sta_remove = il_mac_sta_remove,  	.tx_last_beacon = il_mac_tx_last_beacon, +	.flush = il_mac_flush,  };  static int @@ -3548,7 +3567,8 @@ il3945_setup_mac(struct il_priv *il)  	hw->vif_data_size = sizeof(struct il_vif_priv);  	/* Tell mac80211 our characteristics */ -	hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT; +	hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT | +		    IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS;  	hw->wiphy->interface_modes =  	    BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); @@ -3557,6 +3577,8 @@ il3945_setup_mac(struct il_priv *il)  	    WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS |  	    WIPHY_FLAG_IBSS_RSN; +	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; +  	hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;  	/* we create the 802.11 header and a zero-length SSID element */  	hw->wiphy->max_scan_ie_len = IL3945_MAX_PROBE_REQUEST - 24 - 2;  |